├── .gitattributes ├── .gitignore ├── Angular.SecureStarter.sln ├── License.txt ├── Nuget ├── MakeAll.bat ├── SecureStarter │ ├── AngularJs.StarterKit.SecureStarter.nuspec │ └── CreatePackage.bat ├── Secured.Client │ ├── AngularJs.StarterKit.Spa.Secured.Client.nuspec │ ├── CreatePackage.bat │ ├── tools │ │ └── install.ps1 │ └── transformations.ps1 ├── Secured.Server │ ├── AngularJs.StarterKit.Spa.Secured.Server.nuspec │ ├── CreatePackage.bat │ ├── tools │ │ └── install.ps1 │ └── transformations.ps1 └── Spa │ ├── AngularJs.StarterKit.Spa.nuspec │ ├── CreatePackage.bat │ ├── tools │ └── install.ps1 │ └── transformations.ps1 ├── Secured ├── App_Start │ ├── IdentityConfig.cs │ ├── SecuredClientBundleConfig.cs │ ├── SecuredServerStartup.cs │ ├── SecuredServerWebApiConfig.cs │ ├── SpaBundleConfig.cs │ ├── SpaRouteConfig.cs │ └── Startup.Auth.cs ├── Content │ ├── bootstrap-theme.css │ ├── bootstrap-theme.css.map │ ├── bootstrap-theme.min.css │ ├── bootstrap.css │ ├── bootstrap.css.map │ ├── bootstrap.min.css │ ├── fadeAnimation.css │ ├── spa.css │ ├── toastr.css │ ├── toastr.less │ ├── toastr.min.css │ └── toastr.scss ├── Controllers │ ├── AccountController.cs │ ├── SecuredController.cs │ └── SpaController.cs ├── Filters │ └── RequireHttpsAttribute.cs ├── Icon.png ├── Models │ ├── AccountBindingModels.cs │ ├── AccountViewModels.cs │ ├── ApplicationDbInitializer.cs │ └── IdentityModels.cs ├── Properties │ └── AssemblyInfo.cs ├── Providers │ └── ApplicationOAuthProvider.cs ├── Results │ └── ChallengeResult.cs ├── Scripts │ ├── angular-animate.js │ ├── angular-animate.min.js │ ├── angular-animate.min.js.map │ ├── angular-aria.js │ ├── angular-aria.min.js │ ├── angular-aria.min.js.map │ ├── angular-cookies.js │ ├── angular-cookies.min.js │ ├── angular-cookies.min.js.map │ ├── angular-csp.css │ ├── angular-loader.js │ ├── angular-loader.min.js │ ├── angular-loader.min.js.map │ ├── angular-messages.js │ ├── angular-messages.min.js │ ├── angular-messages.min.js.map │ ├── angular-mocks.js │ ├── angular-resource.js │ ├── angular-resource.min.js │ ├── angular-resource.min.js.map │ ├── angular-route.js │ ├── angular-route.min.js │ ├── angular-route.min.js.map │ ├── angular-sanitize.js │ ├── angular-sanitize.min.js │ ├── angular-sanitize.min.js.map │ ├── angular-scenario.js │ ├── angular-touch.js │ ├── angular-touch.min.js │ ├── angular-touch.min.js.map │ ├── angular.js │ ├── angular.min.js │ ├── angular.min.js.map │ ├── bootstrap.js │ ├── bootstrap.min.js │ ├── errors.json │ ├── i18n │ │ ├── angular-locale_aa-dj.js │ │ ├── angular-locale_aa-er.js │ │ ├── angular-locale_aa-et.js │ │ ├── angular-locale_aa.js │ │ ├── angular-locale_af-na.js │ │ ├── angular-locale_af-za.js │ │ ├── angular-locale_af.js │ │ ├── angular-locale_agq-cm.js │ │ ├── angular-locale_agq.js │ │ ├── angular-locale_ak-gh.js │ │ ├── angular-locale_ak.js │ │ ├── angular-locale_am-et.js │ │ ├── angular-locale_am.js │ │ ├── angular-locale_ar-001.js │ │ ├── angular-locale_ar-ae.js │ │ ├── angular-locale_ar-bh.js │ │ ├── angular-locale_ar-dj.js │ │ ├── angular-locale_ar-dz.js │ │ ├── angular-locale_ar-eg.js │ │ ├── angular-locale_ar-eh.js │ │ ├── angular-locale_ar-er.js │ │ ├── angular-locale_ar-il.js │ │ ├── angular-locale_ar-iq.js │ │ ├── angular-locale_ar-jo.js │ │ ├── angular-locale_ar-km.js │ │ ├── angular-locale_ar-kw.js │ │ ├── angular-locale_ar-lb.js │ │ ├── angular-locale_ar-ly.js │ │ ├── angular-locale_ar-ma.js │ │ ├── angular-locale_ar-mr.js │ │ ├── angular-locale_ar-om.js │ │ ├── angular-locale_ar-ps.js │ │ ├── angular-locale_ar-qa.js │ │ ├── angular-locale_ar-sa.js │ │ ├── angular-locale_ar-sd.js │ │ ├── angular-locale_ar-so.js │ │ ├── angular-locale_ar-ss.js │ │ ├── angular-locale_ar-sy.js │ │ ├── angular-locale_ar-td.js │ │ ├── angular-locale_ar-tn.js │ │ ├── angular-locale_ar-ye.js │ │ ├── angular-locale_ar.js │ │ ├── angular-locale_as-in.js │ │ ├── angular-locale_as.js │ │ ├── angular-locale_asa-tz.js │ │ ├── angular-locale_asa.js │ │ ├── angular-locale_ast-es.js │ │ ├── angular-locale_ast.js │ │ ├── angular-locale_az-cyrl-az.js │ │ ├── angular-locale_az-cyrl.js │ │ ├── angular-locale_az-latn-az.js │ │ ├── angular-locale_az-latn.js │ │ ├── angular-locale_az.js │ │ ├── angular-locale_bas-cm.js │ │ ├── angular-locale_bas.js │ │ ├── angular-locale_be-by.js │ │ ├── angular-locale_be.js │ │ ├── angular-locale_bem-zm.js │ │ ├── angular-locale_bem.js │ │ ├── angular-locale_bez-tz.js │ │ ├── angular-locale_bez.js │ │ ├── angular-locale_bg-bg.js │ │ ├── angular-locale_bg.js │ │ ├── angular-locale_bm-latn-ml.js │ │ ├── angular-locale_bm-latn.js │ │ ├── angular-locale_bm-ml.js │ │ ├── angular-locale_bm.js │ │ ├── angular-locale_bn-bd.js │ │ ├── angular-locale_bn-in.js │ │ ├── angular-locale_bn.js │ │ ├── angular-locale_bo-cn.js │ │ ├── angular-locale_bo-in.js │ │ ├── angular-locale_bo.js │ │ ├── angular-locale_br-fr.js │ │ ├── angular-locale_br.js │ │ ├── angular-locale_brx-in.js │ │ ├── angular-locale_brx.js │ │ ├── angular-locale_bs-cyrl-ba.js │ │ ├── angular-locale_bs-cyrl.js │ │ ├── angular-locale_bs-latn-ba.js │ │ ├── angular-locale_bs-latn.js │ │ ├── angular-locale_bs.js │ │ ├── angular-locale_byn-er.js │ │ ├── angular-locale_byn.js │ │ ├── angular-locale_ca-ad.js │ │ ├── angular-locale_ca-es-valencia.js │ │ ├── angular-locale_ca-es.js │ │ ├── angular-locale_ca-fr.js │ │ ├── angular-locale_ca-it.js │ │ ├── angular-locale_ca.js │ │ ├── angular-locale_cgg-ug.js │ │ ├── angular-locale_cgg.js │ │ ├── angular-locale_chr-us.js │ │ ├── angular-locale_chr.js │ │ ├── angular-locale_ckb-arab-iq.js │ │ ├── angular-locale_ckb-arab-ir.js │ │ ├── angular-locale_ckb-arab.js │ │ ├── angular-locale_ckb-iq.js │ │ ├── angular-locale_ckb-ir.js │ │ ├── angular-locale_ckb-latn-iq.js │ │ ├── angular-locale_ckb-latn.js │ │ ├── angular-locale_ckb.js │ │ ├── angular-locale_cs-cz.js │ │ ├── angular-locale_cs.js │ │ ├── angular-locale_cy-gb.js │ │ ├── angular-locale_cy.js │ │ ├── angular-locale_da-dk.js │ │ ├── angular-locale_da-gl.js │ │ ├── angular-locale_da.js │ │ ├── angular-locale_dav-ke.js │ │ ├── angular-locale_dav.js │ │ ├── angular-locale_de-at.js │ │ ├── angular-locale_de-be.js │ │ ├── angular-locale_de-ch.js │ │ ├── angular-locale_de-de.js │ │ ├── angular-locale_de-li.js │ │ ├── angular-locale_de-lu.js │ │ ├── angular-locale_de.js │ │ ├── angular-locale_dje-ne.js │ │ ├── angular-locale_dje.js │ │ ├── angular-locale_dsb-de.js │ │ ├── angular-locale_dsb.js │ │ ├── angular-locale_dua-cm.js │ │ ├── angular-locale_dua.js │ │ ├── angular-locale_dyo-sn.js │ │ ├── angular-locale_dyo.js │ │ ├── angular-locale_dz-bt.js │ │ ├── angular-locale_dz.js │ │ ├── angular-locale_ebu-ke.js │ │ ├── angular-locale_ebu.js │ │ ├── angular-locale_ee-gh.js │ │ ├── angular-locale_ee-tg.js │ │ ├── angular-locale_ee.js │ │ ├── angular-locale_el-cy.js │ │ ├── angular-locale_el-gr.js │ │ ├── angular-locale_el.js │ │ ├── angular-locale_en-001.js │ │ ├── angular-locale_en-150.js │ │ ├── angular-locale_en-ag.js │ │ ├── angular-locale_en-ai.js │ │ ├── angular-locale_en-as.js │ │ ├── angular-locale_en-au.js │ │ ├── angular-locale_en-bb.js │ │ ├── angular-locale_en-be.js │ │ ├── angular-locale_en-bm.js │ │ ├── angular-locale_en-bs.js │ │ ├── angular-locale_en-bw.js │ │ ├── angular-locale_en-bz.js │ │ ├── angular-locale_en-ca.js │ │ ├── angular-locale_en-cc.js │ │ ├── angular-locale_en-ck.js │ │ ├── angular-locale_en-cm.js │ │ ├── angular-locale_en-cx.js │ │ ├── angular-locale_en-dg.js │ │ ├── angular-locale_en-dm.js │ │ ├── angular-locale_en-er.js │ │ ├── angular-locale_en-fj.js │ │ ├── angular-locale_en-fk.js │ │ ├── angular-locale_en-fm.js │ │ ├── angular-locale_en-gb.js │ │ ├── angular-locale_en-gd.js │ │ ├── angular-locale_en-gg.js │ │ ├── angular-locale_en-gh.js │ │ ├── angular-locale_en-gi.js │ │ ├── angular-locale_en-gm.js │ │ ├── angular-locale_en-gu.js │ │ ├── angular-locale_en-gy.js │ │ ├── angular-locale_en-hk.js │ │ ├── angular-locale_en-ie.js │ │ ├── angular-locale_en-im.js │ │ ├── angular-locale_en-in.js │ │ ├── angular-locale_en-io.js │ │ ├── angular-locale_en-iso.js │ │ ├── angular-locale_en-je.js │ │ ├── angular-locale_en-jm.js │ │ ├── angular-locale_en-ke.js │ │ ├── angular-locale_en-ki.js │ │ ├── angular-locale_en-kn.js │ │ ├── angular-locale_en-ky.js │ │ ├── angular-locale_en-lc.js │ │ ├── angular-locale_en-lr.js │ │ ├── angular-locale_en-ls.js │ │ ├── angular-locale_en-mg.js │ │ ├── angular-locale_en-mh.js │ │ ├── angular-locale_en-mo.js │ │ ├── angular-locale_en-mp.js │ │ ├── angular-locale_en-ms.js │ │ ├── angular-locale_en-mt.js │ │ ├── angular-locale_en-mu.js │ │ ├── angular-locale_en-mw.js │ │ ├── angular-locale_en-my.js │ │ ├── angular-locale_en-na.js │ │ ├── angular-locale_en-nf.js │ │ ├── angular-locale_en-ng.js │ │ ├── angular-locale_en-nr.js │ │ ├── angular-locale_en-nu.js │ │ ├── angular-locale_en-nz.js │ │ ├── angular-locale_en-pg.js │ │ ├── angular-locale_en-ph.js │ │ ├── angular-locale_en-pk.js │ │ ├── angular-locale_en-pn.js │ │ ├── angular-locale_en-pr.js │ │ ├── angular-locale_en-pw.js │ │ ├── angular-locale_en-rw.js │ │ ├── angular-locale_en-sb.js │ │ ├── angular-locale_en-sc.js │ │ ├── angular-locale_en-sd.js │ │ ├── angular-locale_en-sg.js │ │ ├── angular-locale_en-sh.js │ │ ├── angular-locale_en-sl.js │ │ ├── angular-locale_en-ss.js │ │ ├── angular-locale_en-sx.js │ │ ├── angular-locale_en-sz.js │ │ ├── angular-locale_en-tc.js │ │ ├── angular-locale_en-tk.js │ │ ├── angular-locale_en-to.js │ │ ├── angular-locale_en-tt.js │ │ ├── angular-locale_en-tv.js │ │ ├── angular-locale_en-tz.js │ │ ├── angular-locale_en-ug.js │ │ ├── angular-locale_en-um.js │ │ ├── angular-locale_en-us.js │ │ ├── angular-locale_en-vc.js │ │ ├── angular-locale_en-vg.js │ │ ├── angular-locale_en-vi.js │ │ ├── angular-locale_en-vu.js │ │ ├── angular-locale_en-ws.js │ │ ├── angular-locale_en-za.js │ │ ├── angular-locale_en-zm.js │ │ ├── angular-locale_en-zw.js │ │ ├── angular-locale_en.js │ │ ├── angular-locale_eo-001.js │ │ ├── angular-locale_eo.js │ │ ├── angular-locale_es-419.js │ │ ├── angular-locale_es-ar.js │ │ ├── angular-locale_es-bo.js │ │ ├── angular-locale_es-cl.js │ │ ├── angular-locale_es-co.js │ │ ├── angular-locale_es-cr.js │ │ ├── angular-locale_es-cu.js │ │ ├── angular-locale_es-do.js │ │ ├── angular-locale_es-ea.js │ │ ├── angular-locale_es-ec.js │ │ ├── angular-locale_es-es.js │ │ ├── angular-locale_es-gq.js │ │ ├── angular-locale_es-gt.js │ │ ├── angular-locale_es-hn.js │ │ ├── angular-locale_es-ic.js │ │ ├── angular-locale_es-mx.js │ │ ├── angular-locale_es-ni.js │ │ ├── angular-locale_es-pa.js │ │ ├── angular-locale_es-pe.js │ │ ├── angular-locale_es-ph.js │ │ ├── angular-locale_es-pr.js │ │ ├── angular-locale_es-py.js │ │ ├── angular-locale_es-sv.js │ │ ├── angular-locale_es-us.js │ │ ├── angular-locale_es-uy.js │ │ ├── angular-locale_es-ve.js │ │ ├── angular-locale_es.js │ │ ├── angular-locale_et-ee.js │ │ ├── angular-locale_et.js │ │ ├── angular-locale_eu-es.js │ │ ├── angular-locale_eu.js │ │ ├── angular-locale_ewo-cm.js │ │ ├── angular-locale_ewo.js │ │ ├── angular-locale_fa-af.js │ │ ├── angular-locale_fa-ir.js │ │ ├── angular-locale_fa.js │ │ ├── angular-locale_ff-cm.js │ │ ├── angular-locale_ff-gn.js │ │ ├── angular-locale_ff-mr.js │ │ ├── angular-locale_ff-sn.js │ │ ├── angular-locale_ff.js │ │ ├── angular-locale_fi-fi.js │ │ ├── angular-locale_fi.js │ │ ├── angular-locale_fil-ph.js │ │ ├── angular-locale_fil.js │ │ ├── angular-locale_fo-fo.js │ │ ├── angular-locale_fo.js │ │ ├── angular-locale_fr-be.js │ │ ├── angular-locale_fr-bf.js │ │ ├── angular-locale_fr-bi.js │ │ ├── angular-locale_fr-bj.js │ │ ├── angular-locale_fr-bl.js │ │ ├── angular-locale_fr-ca.js │ │ ├── angular-locale_fr-cd.js │ │ ├── angular-locale_fr-cf.js │ │ ├── angular-locale_fr-cg.js │ │ ├── angular-locale_fr-ch.js │ │ ├── angular-locale_fr-ci.js │ │ ├── angular-locale_fr-cm.js │ │ ├── angular-locale_fr-dj.js │ │ ├── angular-locale_fr-dz.js │ │ ├── angular-locale_fr-fr.js │ │ ├── angular-locale_fr-ga.js │ │ ├── angular-locale_fr-gf.js │ │ ├── angular-locale_fr-gn.js │ │ ├── angular-locale_fr-gp.js │ │ ├── angular-locale_fr-gq.js │ │ ├── angular-locale_fr-ht.js │ │ ├── angular-locale_fr-km.js │ │ ├── angular-locale_fr-lu.js │ │ ├── angular-locale_fr-ma.js │ │ ├── angular-locale_fr-mc.js │ │ ├── angular-locale_fr-mf.js │ │ ├── angular-locale_fr-mg.js │ │ ├── angular-locale_fr-ml.js │ │ ├── angular-locale_fr-mq.js │ │ ├── angular-locale_fr-mr.js │ │ ├── angular-locale_fr-mu.js │ │ ├── angular-locale_fr-nc.js │ │ ├── angular-locale_fr-ne.js │ │ ├── angular-locale_fr-pf.js │ │ ├── angular-locale_fr-pm.js │ │ ├── angular-locale_fr-re.js │ │ ├── angular-locale_fr-rw.js │ │ ├── angular-locale_fr-sc.js │ │ ├── angular-locale_fr-sn.js │ │ ├── angular-locale_fr-sy.js │ │ ├── angular-locale_fr-td.js │ │ ├── angular-locale_fr-tg.js │ │ ├── angular-locale_fr-tn.js │ │ ├── angular-locale_fr-vu.js │ │ ├── angular-locale_fr-wf.js │ │ ├── angular-locale_fr-yt.js │ │ ├── angular-locale_fr.js │ │ ├── angular-locale_fur-it.js │ │ ├── angular-locale_fur.js │ │ ├── angular-locale_fy-nl.js │ │ ├── angular-locale_fy.js │ │ ├── angular-locale_ga-ie.js │ │ ├── angular-locale_ga.js │ │ ├── angular-locale_gd-gb.js │ │ ├── angular-locale_gd.js │ │ ├── angular-locale_gl-es.js │ │ ├── angular-locale_gl.js │ │ ├── angular-locale_gsw-ch.js │ │ ├── angular-locale_gsw-fr.js │ │ ├── angular-locale_gsw-li.js │ │ ├── angular-locale_gsw.js │ │ ├── angular-locale_gu-in.js │ │ ├── angular-locale_gu.js │ │ ├── angular-locale_guz-ke.js │ │ ├── angular-locale_guz.js │ │ ├── angular-locale_gv-im.js │ │ ├── angular-locale_gv.js │ │ ├── angular-locale_ha-latn-gh.js │ │ ├── angular-locale_ha-latn-ne.js │ │ ├── angular-locale_ha-latn-ng.js │ │ ├── angular-locale_ha-latn.js │ │ ├── angular-locale_ha.js │ │ ├── angular-locale_haw-us.js │ │ ├── angular-locale_haw.js │ │ ├── angular-locale_he-il.js │ │ ├── angular-locale_he.js │ │ ├── angular-locale_hi-in.js │ │ ├── angular-locale_hi.js │ │ ├── angular-locale_hr-ba.js │ │ ├── angular-locale_hr-hr.js │ │ ├── angular-locale_hr.js │ │ ├── angular-locale_hsb-de.js │ │ ├── angular-locale_hsb.js │ │ ├── angular-locale_hu-hu.js │ │ ├── angular-locale_hu.js │ │ ├── angular-locale_hy-am.js │ │ ├── angular-locale_hy.js │ │ ├── angular-locale_ia-fr.js │ │ ├── angular-locale_ia.js │ │ ├── angular-locale_id-id.js │ │ ├── angular-locale_id.js │ │ ├── angular-locale_ig-ng.js │ │ ├── angular-locale_ig.js │ │ ├── angular-locale_ii-cn.js │ │ ├── angular-locale_ii.js │ │ ├── angular-locale_in.js │ │ ├── angular-locale_is-is.js │ │ ├── angular-locale_is.js │ │ ├── angular-locale_it-ch.js │ │ ├── angular-locale_it-it.js │ │ ├── angular-locale_it-sm.js │ │ ├── angular-locale_it.js │ │ ├── angular-locale_iw.js │ │ ├── angular-locale_ja-jp.js │ │ ├── angular-locale_ja.js │ │ ├── angular-locale_jgo-cm.js │ │ ├── angular-locale_jgo.js │ │ ├── angular-locale_jmc-tz.js │ │ ├── angular-locale_jmc.js │ │ ├── angular-locale_ka-ge.js │ │ ├── angular-locale_ka.js │ │ ├── angular-locale_kab-dz.js │ │ ├── angular-locale_kab.js │ │ ├── angular-locale_kam-ke.js │ │ ├── angular-locale_kam.js │ │ ├── angular-locale_kde-tz.js │ │ ├── angular-locale_kde.js │ │ ├── angular-locale_kea-cv.js │ │ ├── angular-locale_kea.js │ │ ├── angular-locale_khq-ml.js │ │ ├── angular-locale_khq.js │ │ ├── angular-locale_ki-ke.js │ │ ├── angular-locale_ki.js │ │ ├── angular-locale_kk-cyrl-kz.js │ │ ├── angular-locale_kk-cyrl.js │ │ ├── angular-locale_kk.js │ │ ├── angular-locale_kkj-cm.js │ │ ├── angular-locale_kkj.js │ │ ├── angular-locale_kl-gl.js │ │ ├── angular-locale_kl.js │ │ ├── angular-locale_kln-ke.js │ │ ├── angular-locale_kln.js │ │ ├── angular-locale_km-kh.js │ │ ├── angular-locale_km.js │ │ ├── angular-locale_kn-in.js │ │ ├── angular-locale_kn.js │ │ ├── angular-locale_ko-kp.js │ │ ├── angular-locale_ko-kr.js │ │ ├── angular-locale_ko.js │ │ ├── angular-locale_kok-in.js │ │ ├── angular-locale_kok.js │ │ ├── angular-locale_ks-arab-in.js │ │ ├── angular-locale_ks-arab.js │ │ ├── angular-locale_ks.js │ │ ├── angular-locale_ksb-tz.js │ │ ├── angular-locale_ksb.js │ │ ├── angular-locale_ksf-cm.js │ │ ├── angular-locale_ksf.js │ │ ├── angular-locale_ksh-de.js │ │ ├── angular-locale_ksh.js │ │ ├── angular-locale_kw-gb.js │ │ ├── angular-locale_kw.js │ │ ├── angular-locale_ky-cyrl-kg.js │ │ ├── angular-locale_ky-cyrl.js │ │ ├── angular-locale_ky.js │ │ ├── angular-locale_lag-tz.js │ │ ├── angular-locale_lag.js │ │ ├── angular-locale_lb-lu.js │ │ ├── angular-locale_lb.js │ │ ├── angular-locale_lg-ug.js │ │ ├── angular-locale_lg.js │ │ ├── angular-locale_lkt-us.js │ │ ├── angular-locale_lkt.js │ │ ├── angular-locale_ln-ao.js │ │ ├── angular-locale_ln-cd.js │ │ ├── angular-locale_ln-cf.js │ │ ├── angular-locale_ln-cg.js │ │ ├── angular-locale_ln.js │ │ ├── angular-locale_lo-la.js │ │ ├── angular-locale_lo.js │ │ ├── angular-locale_lt-lt.js │ │ ├── angular-locale_lt.js │ │ ├── angular-locale_lu-cd.js │ │ ├── angular-locale_lu.js │ │ ├── angular-locale_luo-ke.js │ │ ├── angular-locale_luo.js │ │ ├── angular-locale_luy-ke.js │ │ ├── angular-locale_luy.js │ │ ├── angular-locale_lv-lv.js │ │ ├── angular-locale_lv.js │ │ ├── angular-locale_mas-ke.js │ │ ├── angular-locale_mas-tz.js │ │ ├── angular-locale_mas.js │ │ ├── angular-locale_mer-ke.js │ │ ├── angular-locale_mer.js │ │ ├── angular-locale_mfe-mu.js │ │ ├── angular-locale_mfe.js │ │ ├── angular-locale_mg-mg.js │ │ ├── angular-locale_mg.js │ │ ├── angular-locale_mgh-mz.js │ │ ├── angular-locale_mgh.js │ │ ├── angular-locale_mgo-cm.js │ │ ├── angular-locale_mgo.js │ │ ├── angular-locale_mk-mk.js │ │ ├── angular-locale_mk.js │ │ ├── angular-locale_ml-in.js │ │ ├── angular-locale_ml.js │ │ ├── angular-locale_mn-cyrl-mn.js │ │ ├── angular-locale_mn-cyrl.js │ │ ├── angular-locale_mn.js │ │ ├── angular-locale_mr-in.js │ │ ├── angular-locale_mr.js │ │ ├── angular-locale_ms-latn-bn.js │ │ ├── angular-locale_ms-latn-my.js │ │ ├── angular-locale_ms-latn-sg.js │ │ ├── angular-locale_ms-latn.js │ │ ├── angular-locale_ms.js │ │ ├── angular-locale_mt-mt.js │ │ ├── angular-locale_mt.js │ │ ├── angular-locale_mua-cm.js │ │ ├── angular-locale_mua.js │ │ ├── angular-locale_my-mm.js │ │ ├── angular-locale_my.js │ │ ├── angular-locale_naq-na.js │ │ ├── angular-locale_naq.js │ │ ├── angular-locale_nb-no.js │ │ ├── angular-locale_nb-sj.js │ │ ├── angular-locale_nb.js │ │ ├── angular-locale_nd-zw.js │ │ ├── angular-locale_nd.js │ │ ├── angular-locale_ne-in.js │ │ ├── angular-locale_ne-np.js │ │ ├── angular-locale_ne.js │ │ ├── angular-locale_nl-aw.js │ │ ├── angular-locale_nl-be.js │ │ ├── angular-locale_nl-bq.js │ │ ├── angular-locale_nl-cw.js │ │ ├── angular-locale_nl-nl.js │ │ ├── angular-locale_nl-sr.js │ │ ├── angular-locale_nl-sx.js │ │ ├── angular-locale_nl.js │ │ ├── angular-locale_nmg-cm.js │ │ ├── angular-locale_nmg.js │ │ ├── angular-locale_nn-no.js │ │ ├── angular-locale_nn.js │ │ ├── angular-locale_nnh-cm.js │ │ ├── angular-locale_nnh.js │ │ ├── angular-locale_no-no.js │ │ ├── angular-locale_no.js │ │ ├── angular-locale_nr-za.js │ │ ├── angular-locale_nr.js │ │ ├── angular-locale_nso-za.js │ │ ├── angular-locale_nso.js │ │ ├── angular-locale_nus-sd.js │ │ ├── angular-locale_nus.js │ │ ├── angular-locale_nyn-ug.js │ │ ├── angular-locale_nyn.js │ │ ├── angular-locale_om-et.js │ │ ├── angular-locale_om-ke.js │ │ ├── angular-locale_om.js │ │ ├── angular-locale_or-in.js │ │ ├── angular-locale_or.js │ │ ├── angular-locale_os-ge.js │ │ ├── angular-locale_os-ru.js │ │ ├── angular-locale_os.js │ │ ├── angular-locale_pa-arab-pk.js │ │ ├── angular-locale_pa-arab.js │ │ ├── angular-locale_pa-guru-in.js │ │ ├── angular-locale_pa-guru.js │ │ ├── angular-locale_pa.js │ │ ├── angular-locale_pl-pl.js │ │ ├── angular-locale_pl.js │ │ ├── angular-locale_ps-af.js │ │ ├── angular-locale_ps.js │ │ ├── angular-locale_pt-ao.js │ │ ├── angular-locale_pt-br.js │ │ ├── angular-locale_pt-cv.js │ │ ├── angular-locale_pt-gw.js │ │ ├── angular-locale_pt-mo.js │ │ ├── angular-locale_pt-mz.js │ │ ├── angular-locale_pt-pt.js │ │ ├── angular-locale_pt-st.js │ │ ├── angular-locale_pt-tl.js │ │ ├── angular-locale_pt.js │ │ ├── angular-locale_qu-bo.js │ │ ├── angular-locale_qu-ec.js │ │ ├── angular-locale_qu-pe.js │ │ ├── angular-locale_qu.js │ │ ├── angular-locale_rm-ch.js │ │ ├── angular-locale_rm.js │ │ ├── angular-locale_rn-bi.js │ │ ├── angular-locale_rn.js │ │ ├── angular-locale_ro-md.js │ │ ├── angular-locale_ro-ro.js │ │ ├── angular-locale_ro.js │ │ ├── angular-locale_rof-tz.js │ │ ├── angular-locale_rof.js │ │ ├── angular-locale_ru-by.js │ │ ├── angular-locale_ru-kg.js │ │ ├── angular-locale_ru-kz.js │ │ ├── angular-locale_ru-md.js │ │ ├── angular-locale_ru-ru.js │ │ ├── angular-locale_ru-ua.js │ │ ├── angular-locale_ru.js │ │ ├── angular-locale_rw-rw.js │ │ ├── angular-locale_rw.js │ │ ├── angular-locale_rwk-tz.js │ │ ├── angular-locale_rwk.js │ │ ├── angular-locale_sah-ru.js │ │ ├── angular-locale_sah.js │ │ ├── angular-locale_saq-ke.js │ │ ├── angular-locale_saq.js │ │ ├── angular-locale_sbp-tz.js │ │ ├── angular-locale_sbp.js │ │ ├── angular-locale_se-fi.js │ │ ├── angular-locale_se-no.js │ │ ├── angular-locale_se-se.js │ │ ├── angular-locale_se.js │ │ ├── angular-locale_seh-mz.js │ │ ├── angular-locale_seh.js │ │ ├── angular-locale_ses-ml.js │ │ ├── angular-locale_ses.js │ │ ├── angular-locale_sg-cf.js │ │ ├── angular-locale_sg.js │ │ ├── angular-locale_shi-latn-ma.js │ │ ├── angular-locale_shi-latn.js │ │ ├── angular-locale_shi-tfng-ma.js │ │ ├── angular-locale_shi-tfng.js │ │ ├── angular-locale_shi.js │ │ ├── angular-locale_si-lk.js │ │ ├── angular-locale_si.js │ │ ├── angular-locale_sk-sk.js │ │ ├── angular-locale_sk.js │ │ ├── angular-locale_sl-si.js │ │ ├── angular-locale_sl.js │ │ ├── angular-locale_smn-fi.js │ │ ├── angular-locale_smn.js │ │ ├── angular-locale_sn-zw.js │ │ ├── angular-locale_sn.js │ │ ├── angular-locale_so-dj.js │ │ ├── angular-locale_so-et.js │ │ ├── angular-locale_so-ke.js │ │ ├── angular-locale_so-so.js │ │ ├── angular-locale_so.js │ │ ├── angular-locale_sq-al.js │ │ ├── angular-locale_sq-mk.js │ │ ├── angular-locale_sq-xk.js │ │ ├── angular-locale_sq.js │ │ ├── angular-locale_sr-cyrl-ba.js │ │ ├── angular-locale_sr-cyrl-me.js │ │ ├── angular-locale_sr-cyrl-rs.js │ │ ├── angular-locale_sr-cyrl-xk.js │ │ ├── angular-locale_sr-cyrl.js │ │ ├── angular-locale_sr-latn-ba.js │ │ ├── angular-locale_sr-latn-me.js │ │ ├── angular-locale_sr-latn-rs.js │ │ ├── angular-locale_sr-latn-xk.js │ │ ├── angular-locale_sr-latn.js │ │ ├── angular-locale_sr.js │ │ ├── angular-locale_ss-sz.js │ │ ├── angular-locale_ss-za.js │ │ ├── angular-locale_ss.js │ │ ├── angular-locale_ssy-er.js │ │ ├── angular-locale_ssy.js │ │ ├── angular-locale_st-ls.js │ │ ├── angular-locale_st-za.js │ │ ├── angular-locale_st.js │ │ ├── angular-locale_sv-ax.js │ │ ├── angular-locale_sv-fi.js │ │ ├── angular-locale_sv-se.js │ │ ├── angular-locale_sv.js │ │ ├── angular-locale_sw-ke.js │ │ ├── angular-locale_sw-tz.js │ │ ├── angular-locale_sw-ug.js │ │ ├── angular-locale_sw.js │ │ ├── angular-locale_swc-cd.js │ │ ├── angular-locale_swc.js │ │ ├── angular-locale_ta-in.js │ │ ├── angular-locale_ta-lk.js │ │ ├── angular-locale_ta-my.js │ │ ├── angular-locale_ta-sg.js │ │ ├── angular-locale_ta.js │ │ ├── angular-locale_te-in.js │ │ ├── angular-locale_te.js │ │ ├── angular-locale_teo-ke.js │ │ ├── angular-locale_teo-ug.js │ │ ├── angular-locale_teo.js │ │ ├── angular-locale_tg-cyrl-tj.js │ │ ├── angular-locale_tg-cyrl.js │ │ ├── angular-locale_tg.js │ │ ├── angular-locale_th-th.js │ │ ├── angular-locale_th.js │ │ ├── angular-locale_ti-er.js │ │ ├── angular-locale_ti-et.js │ │ ├── angular-locale_ti.js │ │ ├── angular-locale_tig-er.js │ │ ├── angular-locale_tig.js │ │ ├── angular-locale_tl.js │ │ ├── angular-locale_tn-bw.js │ │ ├── angular-locale_tn-za.js │ │ ├── angular-locale_tn.js │ │ ├── angular-locale_to-to.js │ │ ├── angular-locale_to.js │ │ ├── angular-locale_tr-cy.js │ │ ├── angular-locale_tr-tr.js │ │ ├── angular-locale_tr.js │ │ ├── angular-locale_ts-za.js │ │ ├── angular-locale_ts.js │ │ ├── angular-locale_twq-ne.js │ │ ├── angular-locale_twq.js │ │ ├── angular-locale_tzm-latn-ma.js │ │ ├── angular-locale_tzm-latn.js │ │ ├── angular-locale_tzm.js │ │ ├── angular-locale_ug-arab-cn.js │ │ ├── angular-locale_ug-arab.js │ │ ├── angular-locale_ug.js │ │ ├── angular-locale_uk-ua.js │ │ ├── angular-locale_uk.js │ │ ├── angular-locale_ur-in.js │ │ ├── angular-locale_ur-pk.js │ │ ├── angular-locale_ur.js │ │ ├── angular-locale_uz-arab-af.js │ │ ├── angular-locale_uz-arab.js │ │ ├── angular-locale_uz-cyrl-uz.js │ │ ├── angular-locale_uz-cyrl.js │ │ ├── angular-locale_uz-latn-uz.js │ │ ├── angular-locale_uz-latn.js │ │ ├── angular-locale_uz.js │ │ ├── angular-locale_vai-latn-lr.js │ │ ├── angular-locale_vai-latn.js │ │ ├── angular-locale_vai-vaii-lr.js │ │ ├── angular-locale_vai-vaii.js │ │ ├── angular-locale_vai.js │ │ ├── angular-locale_ve-za.js │ │ ├── angular-locale_ve.js │ │ ├── angular-locale_vi-vn.js │ │ ├── angular-locale_vi.js │ │ ├── angular-locale_vo-001.js │ │ ├── angular-locale_vo.js │ │ ├── angular-locale_vun-tz.js │ │ ├── angular-locale_vun.js │ │ ├── angular-locale_wae-ch.js │ │ ├── angular-locale_wae.js │ │ ├── angular-locale_wal-et.js │ │ ├── angular-locale_wal.js │ │ ├── angular-locale_xh-za.js │ │ ├── angular-locale_xh.js │ │ ├── angular-locale_xog-ug.js │ │ ├── angular-locale_xog.js │ │ ├── angular-locale_yav-cm.js │ │ ├── angular-locale_yav.js │ │ ├── angular-locale_yi-001.js │ │ ├── angular-locale_yi.js │ │ ├── angular-locale_yo-bj.js │ │ ├── angular-locale_yo-ng.js │ │ ├── angular-locale_yo.js │ │ ├── angular-locale_zgh-ma.js │ │ ├── angular-locale_zgh.js │ │ ├── angular-locale_zh-cn.js │ │ ├── angular-locale_zh-hans-cn.js │ │ ├── angular-locale_zh-hans-hk.js │ │ ├── angular-locale_zh-hans-mo.js │ │ ├── angular-locale_zh-hans-sg.js │ │ ├── angular-locale_zh-hans.js │ │ ├── angular-locale_zh-hant-hk.js │ │ ├── angular-locale_zh-hant-mo.js │ │ ├── angular-locale_zh-hant-tw.js │ │ ├── angular-locale_zh-hant.js │ │ ├── angular-locale_zh-hk.js │ │ ├── angular-locale_zh-tw.js │ │ ├── angular-locale_zh.js │ │ ├── angular-locale_zu-za.js │ │ └── angular-locale_zu.js │ ├── jquery-2.1.3.intellisense.js │ ├── jquery-2.1.3.js │ ├── jquery-2.1.3.min.js │ ├── jquery-2.1.3.min.map │ ├── modernizr-2.8.3.js │ ├── npm.js │ ├── respond.js │ ├── respond.matchmedia.addListener.js │ ├── respond.matchmedia.addListener.min.js │ ├── respond.min.js │ ├── toastr.js │ ├── toastr.min.js │ └── version.json ├── Secured.csproj ├── Views │ ├── Spa │ │ └── Index.cshtml │ └── web.config ├── Web.Debug.config ├── Web.Release.config ├── Web.config ├── Web.config.install.xdt ├── Web.config.uninstall.xdt ├── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.svg │ ├── glyphicons-halflings-regular.ttf │ ├── glyphicons-halflings-regular.woff │ └── glyphicons-halflings-regular.woff2 ├── packages.config └── spa │ ├── app.js │ ├── common │ ├── common.module.js │ ├── utilityService.js │ └── validation │ │ ├── skAsyncValidators.js │ │ ├── skHasError.js │ │ ├── skMatch.js │ │ └── skUnique.js │ ├── content │ ├── SecuredWebapiDemo │ │ ├── SecuredWebapiDemoController.js │ │ └── securedWebapiDemo.html │ ├── content.module.js │ ├── features │ │ ├── FeaturesController.js │ │ └── features.html │ └── welcome │ │ ├── WelcomeController.js │ │ └── welcome.html │ ├── core │ ├── appActivityService.js │ ├── appStatusService.js │ ├── core.module.js │ ├── navigationService.js │ ├── notifierService.js │ ├── skAppReady.js │ ├── skDisableWhenBusy.js │ ├── skFocusOnSetPristine.js │ └── storageService.js │ ├── security │ ├── ExternalRegisterController.js │ ├── ExternalSignInController.js │ ├── ManageController.js │ ├── RegisterController.js │ ├── SignInController.js │ ├── accountResource.js │ ├── clientIdHttpInterceptor.js │ ├── externalAuthService.js │ ├── externalRegister.html │ ├── externalSignIn.html │ ├── guardService.js │ ├── manage.html │ ├── register.html │ ├── restoreUserService.js │ ├── secureHttpInterceptor.js │ ├── security.module.js │ ├── signIn.html │ ├── skChangePassword.html │ ├── skChangePassword.js │ ├── skCreateLocalLogin.html │ ├── skCreateLocalLogin.js │ ├── skLoginProvider.html │ ├── skLoginProvider.js │ ├── skRequiredRoles.js │ ├── skUserInfo.html │ ├── skUserInfo.js │ ├── skUserLogin.html │ ├── skUserLogin.js │ ├── usedLoginProviderFilter.js │ ├── userManagementService.js │ └── userService.js │ └── shell │ ├── ShellController.js │ ├── shell.html │ ├── shell.module.js │ ├── skBusyIndicator.html │ ├── skBusyIndicator.js │ ├── skLoadingScreen.html │ ├── skLoadingScreen.js │ ├── skNavLink.html │ ├── skNavLink.js │ ├── skNavLinks.html │ ├── skNavLinks.js │ ├── skTopNav.html │ └── skTopNav.js ├── Spa ├── App_Start │ ├── SpaBundleConfig.cs │ └── SpaRouteConfig.cs ├── Content │ ├── bootstrap-theme.css │ ├── bootstrap-theme.css.map │ ├── bootstrap-theme.min.css │ ├── bootstrap.css │ ├── bootstrap.css.map │ ├── bootstrap.min.css │ ├── fadeAnimation.css │ ├── spa.css │ ├── toastr.css │ ├── toastr.less │ ├── toastr.min.css │ └── toastr.scss ├── Controllers │ └── SpaController.cs ├── Icon.png ├── Properties │ └── AssemblyInfo.cs ├── Scripts │ ├── angular-animate.js │ ├── angular-animate.min.js │ ├── angular-animate.min.js.map │ ├── angular-aria.js │ ├── angular-aria.min.js │ ├── angular-aria.min.js.map │ ├── angular-cookies.js │ ├── angular-cookies.min.js │ ├── angular-cookies.min.js.map │ ├── angular-csp.css │ ├── angular-loader.js │ ├── angular-loader.min.js │ ├── angular-loader.min.js.map │ ├── angular-messages.js │ ├── angular-messages.min.js │ ├── angular-messages.min.js.map │ ├── angular-mocks.js │ ├── angular-resource.js │ ├── angular-resource.min.js │ ├── angular-resource.min.js.map │ ├── angular-route.js │ ├── angular-route.min.js │ ├── angular-route.min.js.map │ ├── angular-sanitize.js │ ├── angular-sanitize.min.js │ ├── angular-sanitize.min.js.map │ ├── angular-scenario.js │ ├── angular-touch.js │ ├── angular-touch.min.js │ ├── angular-touch.min.js.map │ ├── angular.js │ ├── angular.min.js │ ├── angular.min.js.map │ ├── bootstrap.js │ ├── bootstrap.min.js │ ├── errors.json │ ├── i18n │ │ ├── angular-locale_aa-dj.js │ │ ├── angular-locale_aa-er.js │ │ ├── angular-locale_aa-et.js │ │ ├── angular-locale_aa.js │ │ ├── angular-locale_af-na.js │ │ ├── angular-locale_af-za.js │ │ ├── angular-locale_af.js │ │ ├── angular-locale_agq-cm.js │ │ ├── angular-locale_agq.js │ │ ├── angular-locale_ak-gh.js │ │ ├── angular-locale_ak.js │ │ ├── angular-locale_am-et.js │ │ ├── angular-locale_am.js │ │ ├── angular-locale_ar-001.js │ │ ├── angular-locale_ar-ae.js │ │ ├── angular-locale_ar-bh.js │ │ ├── angular-locale_ar-dj.js │ │ ├── angular-locale_ar-dz.js │ │ ├── angular-locale_ar-eg.js │ │ ├── angular-locale_ar-eh.js │ │ ├── angular-locale_ar-er.js │ │ ├── angular-locale_ar-il.js │ │ ├── angular-locale_ar-iq.js │ │ ├── angular-locale_ar-jo.js │ │ ├── angular-locale_ar-km.js │ │ ├── angular-locale_ar-kw.js │ │ ├── angular-locale_ar-lb.js │ │ ├── angular-locale_ar-ly.js │ │ ├── angular-locale_ar-ma.js │ │ ├── angular-locale_ar-mr.js │ │ ├── angular-locale_ar-om.js │ │ ├── angular-locale_ar-ps.js │ │ ├── angular-locale_ar-qa.js │ │ ├── angular-locale_ar-sa.js │ │ ├── angular-locale_ar-sd.js │ │ ├── angular-locale_ar-so.js │ │ ├── angular-locale_ar-ss.js │ │ ├── angular-locale_ar-sy.js │ │ ├── angular-locale_ar-td.js │ │ ├── angular-locale_ar-tn.js │ │ ├── angular-locale_ar-ye.js │ │ ├── angular-locale_ar.js │ │ ├── angular-locale_as-in.js │ │ ├── angular-locale_as.js │ │ ├── angular-locale_asa-tz.js │ │ ├── angular-locale_asa.js │ │ ├── angular-locale_ast-es.js │ │ ├── angular-locale_ast.js │ │ ├── angular-locale_az-cyrl-az.js │ │ ├── angular-locale_az-cyrl.js │ │ ├── angular-locale_az-latn-az.js │ │ ├── angular-locale_az-latn.js │ │ ├── angular-locale_az.js │ │ ├── angular-locale_bas-cm.js │ │ ├── angular-locale_bas.js │ │ ├── angular-locale_be-by.js │ │ ├── angular-locale_be.js │ │ ├── angular-locale_bem-zm.js │ │ ├── angular-locale_bem.js │ │ ├── angular-locale_bez-tz.js │ │ ├── angular-locale_bez.js │ │ ├── angular-locale_bg-bg.js │ │ ├── angular-locale_bg.js │ │ ├── angular-locale_bm-latn-ml.js │ │ ├── angular-locale_bm-latn.js │ │ ├── angular-locale_bm-ml.js │ │ ├── angular-locale_bm.js │ │ ├── angular-locale_bn-bd.js │ │ ├── angular-locale_bn-in.js │ │ ├── angular-locale_bn.js │ │ ├── angular-locale_bo-cn.js │ │ ├── angular-locale_bo-in.js │ │ ├── angular-locale_bo.js │ │ ├── angular-locale_br-fr.js │ │ ├── angular-locale_br.js │ │ ├── angular-locale_brx-in.js │ │ ├── angular-locale_brx.js │ │ ├── angular-locale_bs-cyrl-ba.js │ │ ├── angular-locale_bs-cyrl.js │ │ ├── angular-locale_bs-latn-ba.js │ │ ├── angular-locale_bs-latn.js │ │ ├── angular-locale_bs.js │ │ ├── angular-locale_byn-er.js │ │ ├── angular-locale_byn.js │ │ ├── angular-locale_ca-ad.js │ │ ├── angular-locale_ca-es-valencia.js │ │ ├── angular-locale_ca-es.js │ │ ├── angular-locale_ca-fr.js │ │ ├── angular-locale_ca-it.js │ │ ├── angular-locale_ca.js │ │ ├── angular-locale_cgg-ug.js │ │ ├── angular-locale_cgg.js │ │ ├── angular-locale_chr-us.js │ │ ├── angular-locale_chr.js │ │ ├── angular-locale_ckb-arab-iq.js │ │ ├── angular-locale_ckb-arab-ir.js │ │ ├── angular-locale_ckb-arab.js │ │ ├── angular-locale_ckb-iq.js │ │ ├── angular-locale_ckb-ir.js │ │ ├── angular-locale_ckb-latn-iq.js │ │ ├── angular-locale_ckb-latn.js │ │ ├── angular-locale_ckb.js │ │ ├── angular-locale_cs-cz.js │ │ ├── angular-locale_cs.js │ │ ├── angular-locale_cy-gb.js │ │ ├── angular-locale_cy.js │ │ ├── angular-locale_da-dk.js │ │ ├── angular-locale_da-gl.js │ │ ├── angular-locale_da.js │ │ ├── angular-locale_dav-ke.js │ │ ├── angular-locale_dav.js │ │ ├── angular-locale_de-at.js │ │ ├── angular-locale_de-be.js │ │ ├── angular-locale_de-ch.js │ │ ├── angular-locale_de-de.js │ │ ├── angular-locale_de-li.js │ │ ├── angular-locale_de-lu.js │ │ ├── angular-locale_de.js │ │ ├── angular-locale_dje-ne.js │ │ ├── angular-locale_dje.js │ │ ├── angular-locale_dsb-de.js │ │ ├── angular-locale_dsb.js │ │ ├── angular-locale_dua-cm.js │ │ ├── angular-locale_dua.js │ │ ├── angular-locale_dyo-sn.js │ │ ├── angular-locale_dyo.js │ │ ├── angular-locale_dz-bt.js │ │ ├── angular-locale_dz.js │ │ ├── angular-locale_ebu-ke.js │ │ ├── angular-locale_ebu.js │ │ ├── angular-locale_ee-gh.js │ │ ├── angular-locale_ee-tg.js │ │ ├── angular-locale_ee.js │ │ ├── angular-locale_el-cy.js │ │ ├── angular-locale_el-gr.js │ │ ├── angular-locale_el.js │ │ ├── angular-locale_en-001.js │ │ ├── angular-locale_en-150.js │ │ ├── angular-locale_en-ag.js │ │ ├── angular-locale_en-ai.js │ │ ├── angular-locale_en-as.js │ │ ├── angular-locale_en-au.js │ │ ├── angular-locale_en-bb.js │ │ ├── angular-locale_en-be.js │ │ ├── angular-locale_en-bm.js │ │ ├── angular-locale_en-bs.js │ │ ├── angular-locale_en-bw.js │ │ ├── angular-locale_en-bz.js │ │ ├── angular-locale_en-ca.js │ │ ├── angular-locale_en-cc.js │ │ ├── angular-locale_en-ck.js │ │ ├── angular-locale_en-cm.js │ │ ├── angular-locale_en-cx.js │ │ ├── angular-locale_en-dg.js │ │ ├── angular-locale_en-dm.js │ │ ├── angular-locale_en-er.js │ │ ├── angular-locale_en-fj.js │ │ ├── angular-locale_en-fk.js │ │ ├── angular-locale_en-fm.js │ │ ├── angular-locale_en-gb.js │ │ ├── angular-locale_en-gd.js │ │ ├── angular-locale_en-gg.js │ │ ├── angular-locale_en-gh.js │ │ ├── angular-locale_en-gi.js │ │ ├── angular-locale_en-gm.js │ │ ├── angular-locale_en-gu.js │ │ ├── angular-locale_en-gy.js │ │ ├── angular-locale_en-hk.js │ │ ├── angular-locale_en-ie.js │ │ ├── angular-locale_en-im.js │ │ ├── angular-locale_en-in.js │ │ ├── angular-locale_en-io.js │ │ ├── angular-locale_en-iso.js │ │ ├── angular-locale_en-je.js │ │ ├── angular-locale_en-jm.js │ │ ├── angular-locale_en-ke.js │ │ ├── angular-locale_en-ki.js │ │ ├── angular-locale_en-kn.js │ │ ├── angular-locale_en-ky.js │ │ ├── angular-locale_en-lc.js │ │ ├── angular-locale_en-lr.js │ │ ├── angular-locale_en-ls.js │ │ ├── angular-locale_en-mg.js │ │ ├── angular-locale_en-mh.js │ │ ├── angular-locale_en-mo.js │ │ ├── angular-locale_en-mp.js │ │ ├── angular-locale_en-ms.js │ │ ├── angular-locale_en-mt.js │ │ ├── angular-locale_en-mu.js │ │ ├── angular-locale_en-mw.js │ │ ├── angular-locale_en-my.js │ │ ├── angular-locale_en-na.js │ │ ├── angular-locale_en-nf.js │ │ ├── angular-locale_en-ng.js │ │ ├── angular-locale_en-nr.js │ │ ├── angular-locale_en-nu.js │ │ ├── angular-locale_en-nz.js │ │ ├── angular-locale_en-pg.js │ │ ├── angular-locale_en-ph.js │ │ ├── angular-locale_en-pk.js │ │ ├── angular-locale_en-pn.js │ │ ├── angular-locale_en-pr.js │ │ ├── angular-locale_en-pw.js │ │ ├── angular-locale_en-rw.js │ │ ├── angular-locale_en-sb.js │ │ ├── angular-locale_en-sc.js │ │ ├── angular-locale_en-sd.js │ │ ├── angular-locale_en-sg.js │ │ ├── angular-locale_en-sh.js │ │ ├── angular-locale_en-sl.js │ │ ├── angular-locale_en-ss.js │ │ ├── angular-locale_en-sx.js │ │ ├── angular-locale_en-sz.js │ │ ├── angular-locale_en-tc.js │ │ ├── angular-locale_en-tk.js │ │ ├── angular-locale_en-to.js │ │ ├── angular-locale_en-tt.js │ │ ├── angular-locale_en-tv.js │ │ ├── angular-locale_en-tz.js │ │ ├── angular-locale_en-ug.js │ │ ├── angular-locale_en-um.js │ │ ├── angular-locale_en-us.js │ │ ├── angular-locale_en-vc.js │ │ ├── angular-locale_en-vg.js │ │ ├── angular-locale_en-vi.js │ │ ├── angular-locale_en-vu.js │ │ ├── angular-locale_en-ws.js │ │ ├── angular-locale_en-za.js │ │ ├── angular-locale_en-zm.js │ │ ├── angular-locale_en-zw.js │ │ ├── angular-locale_en.js │ │ ├── angular-locale_eo-001.js │ │ ├── angular-locale_eo.js │ │ ├── angular-locale_es-419.js │ │ ├── angular-locale_es-ar.js │ │ ├── angular-locale_es-bo.js │ │ ├── angular-locale_es-cl.js │ │ ├── angular-locale_es-co.js │ │ ├── angular-locale_es-cr.js │ │ ├── angular-locale_es-cu.js │ │ ├── angular-locale_es-do.js │ │ ├── angular-locale_es-ea.js │ │ ├── angular-locale_es-ec.js │ │ ├── angular-locale_es-es.js │ │ ├── angular-locale_es-gq.js │ │ ├── angular-locale_es-gt.js │ │ ├── angular-locale_es-hn.js │ │ ├── angular-locale_es-ic.js │ │ ├── angular-locale_es-mx.js │ │ ├── angular-locale_es-ni.js │ │ ├── angular-locale_es-pa.js │ │ ├── angular-locale_es-pe.js │ │ ├── angular-locale_es-ph.js │ │ ├── angular-locale_es-pr.js │ │ ├── angular-locale_es-py.js │ │ ├── angular-locale_es-sv.js │ │ ├── angular-locale_es-us.js │ │ ├── angular-locale_es-uy.js │ │ ├── angular-locale_es-ve.js │ │ ├── angular-locale_es.js │ │ ├── angular-locale_et-ee.js │ │ ├── angular-locale_et.js │ │ ├── angular-locale_eu-es.js │ │ ├── angular-locale_eu.js │ │ ├── angular-locale_ewo-cm.js │ │ ├── angular-locale_ewo.js │ │ ├── angular-locale_fa-af.js │ │ ├── angular-locale_fa-ir.js │ │ ├── angular-locale_fa.js │ │ ├── angular-locale_ff-cm.js │ │ ├── angular-locale_ff-gn.js │ │ ├── angular-locale_ff-mr.js │ │ ├── angular-locale_ff-sn.js │ │ ├── angular-locale_ff.js │ │ ├── angular-locale_fi-fi.js │ │ ├── angular-locale_fi.js │ │ ├── angular-locale_fil-ph.js │ │ ├── angular-locale_fil.js │ │ ├── angular-locale_fo-fo.js │ │ ├── angular-locale_fo.js │ │ ├── angular-locale_fr-be.js │ │ ├── angular-locale_fr-bf.js │ │ ├── angular-locale_fr-bi.js │ │ ├── angular-locale_fr-bj.js │ │ ├── angular-locale_fr-bl.js │ │ ├── angular-locale_fr-ca.js │ │ ├── angular-locale_fr-cd.js │ │ ├── angular-locale_fr-cf.js │ │ ├── angular-locale_fr-cg.js │ │ ├── angular-locale_fr-ch.js │ │ ├── angular-locale_fr-ci.js │ │ ├── angular-locale_fr-cm.js │ │ ├── angular-locale_fr-dj.js │ │ ├── angular-locale_fr-dz.js │ │ ├── angular-locale_fr-fr.js │ │ ├── angular-locale_fr-ga.js │ │ ├── angular-locale_fr-gf.js │ │ ├── angular-locale_fr-gn.js │ │ ├── angular-locale_fr-gp.js │ │ ├── angular-locale_fr-gq.js │ │ ├── angular-locale_fr-ht.js │ │ ├── angular-locale_fr-km.js │ │ ├── angular-locale_fr-lu.js │ │ ├── angular-locale_fr-ma.js │ │ ├── angular-locale_fr-mc.js │ │ ├── angular-locale_fr-mf.js │ │ ├── angular-locale_fr-mg.js │ │ ├── angular-locale_fr-ml.js │ │ ├── angular-locale_fr-mq.js │ │ ├── angular-locale_fr-mr.js │ │ ├── angular-locale_fr-mu.js │ │ ├── angular-locale_fr-nc.js │ │ ├── angular-locale_fr-ne.js │ │ ├── angular-locale_fr-pf.js │ │ ├── angular-locale_fr-pm.js │ │ ├── angular-locale_fr-re.js │ │ ├── angular-locale_fr-rw.js │ │ ├── angular-locale_fr-sc.js │ │ ├── angular-locale_fr-sn.js │ │ ├── angular-locale_fr-sy.js │ │ ├── angular-locale_fr-td.js │ │ ├── angular-locale_fr-tg.js │ │ ├── angular-locale_fr-tn.js │ │ ├── angular-locale_fr-vu.js │ │ ├── angular-locale_fr-wf.js │ │ ├── angular-locale_fr-yt.js │ │ ├── angular-locale_fr.js │ │ ├── angular-locale_fur-it.js │ │ ├── angular-locale_fur.js │ │ ├── angular-locale_fy-nl.js │ │ ├── angular-locale_fy.js │ │ ├── angular-locale_ga-ie.js │ │ ├── angular-locale_ga.js │ │ ├── angular-locale_gd-gb.js │ │ ├── angular-locale_gd.js │ │ ├── angular-locale_gl-es.js │ │ ├── angular-locale_gl.js │ │ ├── angular-locale_gsw-ch.js │ │ ├── angular-locale_gsw-fr.js │ │ ├── angular-locale_gsw-li.js │ │ ├── angular-locale_gsw.js │ │ ├── angular-locale_gu-in.js │ │ ├── angular-locale_gu.js │ │ ├── angular-locale_guz-ke.js │ │ ├── angular-locale_guz.js │ │ ├── angular-locale_gv-im.js │ │ ├── angular-locale_gv.js │ │ ├── angular-locale_ha-latn-gh.js │ │ ├── angular-locale_ha-latn-ne.js │ │ ├── angular-locale_ha-latn-ng.js │ │ ├── angular-locale_ha-latn.js │ │ ├── angular-locale_ha.js │ │ ├── angular-locale_haw-us.js │ │ ├── angular-locale_haw.js │ │ ├── angular-locale_he-il.js │ │ ├── angular-locale_he.js │ │ ├── angular-locale_hi-in.js │ │ ├── angular-locale_hi.js │ │ ├── angular-locale_hr-ba.js │ │ ├── angular-locale_hr-hr.js │ │ ├── angular-locale_hr.js │ │ ├── angular-locale_hsb-de.js │ │ ├── angular-locale_hsb.js │ │ ├── angular-locale_hu-hu.js │ │ ├── angular-locale_hu.js │ │ ├── angular-locale_hy-am.js │ │ ├── angular-locale_hy.js │ │ ├── angular-locale_ia-fr.js │ │ ├── angular-locale_ia.js │ │ ├── angular-locale_id-id.js │ │ ├── angular-locale_id.js │ │ ├── angular-locale_ig-ng.js │ │ ├── angular-locale_ig.js │ │ ├── angular-locale_ii-cn.js │ │ ├── angular-locale_ii.js │ │ ├── angular-locale_in.js │ │ ├── angular-locale_is-is.js │ │ ├── angular-locale_is.js │ │ ├── angular-locale_it-ch.js │ │ ├── angular-locale_it-it.js │ │ ├── angular-locale_it-sm.js │ │ ├── angular-locale_it.js │ │ ├── angular-locale_iw.js │ │ ├── angular-locale_ja-jp.js │ │ ├── angular-locale_ja.js │ │ ├── angular-locale_jgo-cm.js │ │ ├── angular-locale_jgo.js │ │ ├── angular-locale_jmc-tz.js │ │ ├── angular-locale_jmc.js │ │ ├── angular-locale_ka-ge.js │ │ ├── angular-locale_ka.js │ │ ├── angular-locale_kab-dz.js │ │ ├── angular-locale_kab.js │ │ ├── angular-locale_kam-ke.js │ │ ├── angular-locale_kam.js │ │ ├── angular-locale_kde-tz.js │ │ ├── angular-locale_kde.js │ │ ├── angular-locale_kea-cv.js │ │ ├── angular-locale_kea.js │ │ ├── angular-locale_khq-ml.js │ │ ├── angular-locale_khq.js │ │ ├── angular-locale_ki-ke.js │ │ ├── angular-locale_ki.js │ │ ├── angular-locale_kk-cyrl-kz.js │ │ ├── angular-locale_kk-cyrl.js │ │ ├── angular-locale_kk.js │ │ ├── angular-locale_kkj-cm.js │ │ ├── angular-locale_kkj.js │ │ ├── angular-locale_kl-gl.js │ │ ├── angular-locale_kl.js │ │ ├── angular-locale_kln-ke.js │ │ ├── angular-locale_kln.js │ │ ├── angular-locale_km-kh.js │ │ ├── angular-locale_km.js │ │ ├── angular-locale_kn-in.js │ │ ├── angular-locale_kn.js │ │ ├── angular-locale_ko-kp.js │ │ ├── angular-locale_ko-kr.js │ │ ├── angular-locale_ko.js │ │ ├── angular-locale_kok-in.js │ │ ├── angular-locale_kok.js │ │ ├── angular-locale_ks-arab-in.js │ │ ├── angular-locale_ks-arab.js │ │ ├── angular-locale_ks.js │ │ ├── angular-locale_ksb-tz.js │ │ ├── angular-locale_ksb.js │ │ ├── angular-locale_ksf-cm.js │ │ ├── angular-locale_ksf.js │ │ ├── angular-locale_ksh-de.js │ │ ├── angular-locale_ksh.js │ │ ├── angular-locale_kw-gb.js │ │ ├── angular-locale_kw.js │ │ ├── angular-locale_ky-cyrl-kg.js │ │ ├── angular-locale_ky-cyrl.js │ │ ├── angular-locale_ky.js │ │ ├── angular-locale_lag-tz.js │ │ ├── angular-locale_lag.js │ │ ├── angular-locale_lb-lu.js │ │ ├── angular-locale_lb.js │ │ ├── angular-locale_lg-ug.js │ │ ├── angular-locale_lg.js │ │ ├── angular-locale_lkt-us.js │ │ ├── angular-locale_lkt.js │ │ ├── angular-locale_ln-ao.js │ │ ├── angular-locale_ln-cd.js │ │ ├── angular-locale_ln-cf.js │ │ ├── angular-locale_ln-cg.js │ │ ├── angular-locale_ln.js │ │ ├── angular-locale_lo-la.js │ │ ├── angular-locale_lo.js │ │ ├── angular-locale_lt-lt.js │ │ ├── angular-locale_lt.js │ │ ├── angular-locale_lu-cd.js │ │ ├── angular-locale_lu.js │ │ ├── angular-locale_luo-ke.js │ │ ├── angular-locale_luo.js │ │ ├── angular-locale_luy-ke.js │ │ ├── angular-locale_luy.js │ │ ├── angular-locale_lv-lv.js │ │ ├── angular-locale_lv.js │ │ ├── angular-locale_mas-ke.js │ │ ├── angular-locale_mas-tz.js │ │ ├── angular-locale_mas.js │ │ ├── angular-locale_mer-ke.js │ │ ├── angular-locale_mer.js │ │ ├── angular-locale_mfe-mu.js │ │ ├── angular-locale_mfe.js │ │ ├── angular-locale_mg-mg.js │ │ ├── angular-locale_mg.js │ │ ├── angular-locale_mgh-mz.js │ │ ├── angular-locale_mgh.js │ │ ├── angular-locale_mgo-cm.js │ │ ├── angular-locale_mgo.js │ │ ├── angular-locale_mk-mk.js │ │ ├── angular-locale_mk.js │ │ ├── angular-locale_ml-in.js │ │ ├── angular-locale_ml.js │ │ ├── angular-locale_mn-cyrl-mn.js │ │ ├── angular-locale_mn-cyrl.js │ │ ├── angular-locale_mn.js │ │ ├── angular-locale_mr-in.js │ │ ├── angular-locale_mr.js │ │ ├── angular-locale_ms-latn-bn.js │ │ ├── angular-locale_ms-latn-my.js │ │ ├── angular-locale_ms-latn-sg.js │ │ ├── angular-locale_ms-latn.js │ │ ├── angular-locale_ms.js │ │ ├── angular-locale_mt-mt.js │ │ ├── angular-locale_mt.js │ │ ├── angular-locale_mua-cm.js │ │ ├── angular-locale_mua.js │ │ ├── angular-locale_my-mm.js │ │ ├── angular-locale_my.js │ │ ├── angular-locale_naq-na.js │ │ ├── angular-locale_naq.js │ │ ├── angular-locale_nb-no.js │ │ ├── angular-locale_nb-sj.js │ │ ├── angular-locale_nb.js │ │ ├── angular-locale_nd-zw.js │ │ ├── angular-locale_nd.js │ │ ├── angular-locale_ne-in.js │ │ ├── angular-locale_ne-np.js │ │ ├── angular-locale_ne.js │ │ ├── angular-locale_nl-aw.js │ │ ├── angular-locale_nl-be.js │ │ ├── angular-locale_nl-bq.js │ │ ├── angular-locale_nl-cw.js │ │ ├── angular-locale_nl-nl.js │ │ ├── angular-locale_nl-sr.js │ │ ├── angular-locale_nl-sx.js │ │ ├── angular-locale_nl.js │ │ ├── angular-locale_nmg-cm.js │ │ ├── angular-locale_nmg.js │ │ ├── angular-locale_nn-no.js │ │ ├── angular-locale_nn.js │ │ ├── angular-locale_nnh-cm.js │ │ ├── angular-locale_nnh.js │ │ ├── angular-locale_no-no.js │ │ ├── angular-locale_no.js │ │ ├── angular-locale_nr-za.js │ │ ├── angular-locale_nr.js │ │ ├── angular-locale_nso-za.js │ │ ├── angular-locale_nso.js │ │ ├── angular-locale_nus-sd.js │ │ ├── angular-locale_nus.js │ │ ├── angular-locale_nyn-ug.js │ │ ├── angular-locale_nyn.js │ │ ├── angular-locale_om-et.js │ │ ├── angular-locale_om-ke.js │ │ ├── angular-locale_om.js │ │ ├── angular-locale_or-in.js │ │ ├── angular-locale_or.js │ │ ├── angular-locale_os-ge.js │ │ ├── angular-locale_os-ru.js │ │ ├── angular-locale_os.js │ │ ├── angular-locale_pa-arab-pk.js │ │ ├── angular-locale_pa-arab.js │ │ ├── angular-locale_pa-guru-in.js │ │ ├── angular-locale_pa-guru.js │ │ ├── angular-locale_pa.js │ │ ├── angular-locale_pl-pl.js │ │ ├── angular-locale_pl.js │ │ ├── angular-locale_ps-af.js │ │ ├── angular-locale_ps.js │ │ ├── angular-locale_pt-ao.js │ │ ├── angular-locale_pt-br.js │ │ ├── angular-locale_pt-cv.js │ │ ├── angular-locale_pt-gw.js │ │ ├── angular-locale_pt-mo.js │ │ ├── angular-locale_pt-mz.js │ │ ├── angular-locale_pt-pt.js │ │ ├── angular-locale_pt-st.js │ │ ├── angular-locale_pt-tl.js │ │ ├── angular-locale_pt.js │ │ ├── angular-locale_qu-bo.js │ │ ├── angular-locale_qu-ec.js │ │ ├── angular-locale_qu-pe.js │ │ ├── angular-locale_qu.js │ │ ├── angular-locale_rm-ch.js │ │ ├── angular-locale_rm.js │ │ ├── angular-locale_rn-bi.js │ │ ├── angular-locale_rn.js │ │ ├── angular-locale_ro-md.js │ │ ├── angular-locale_ro-ro.js │ │ ├── angular-locale_ro.js │ │ ├── angular-locale_rof-tz.js │ │ ├── angular-locale_rof.js │ │ ├── angular-locale_ru-by.js │ │ ├── angular-locale_ru-kg.js │ │ ├── angular-locale_ru-kz.js │ │ ├── angular-locale_ru-md.js │ │ ├── angular-locale_ru-ru.js │ │ ├── angular-locale_ru-ua.js │ │ ├── angular-locale_ru.js │ │ ├── angular-locale_rw-rw.js │ │ ├── angular-locale_rw.js │ │ ├── angular-locale_rwk-tz.js │ │ ├── angular-locale_rwk.js │ │ ├── angular-locale_sah-ru.js │ │ ├── angular-locale_sah.js │ │ ├── angular-locale_saq-ke.js │ │ ├── angular-locale_saq.js │ │ ├── angular-locale_sbp-tz.js │ │ ├── angular-locale_sbp.js │ │ ├── angular-locale_se-fi.js │ │ ├── angular-locale_se-no.js │ │ ├── angular-locale_se-se.js │ │ ├── angular-locale_se.js │ │ ├── angular-locale_seh-mz.js │ │ ├── angular-locale_seh.js │ │ ├── angular-locale_ses-ml.js │ │ ├── angular-locale_ses.js │ │ ├── angular-locale_sg-cf.js │ │ ├── angular-locale_sg.js │ │ ├── angular-locale_shi-latn-ma.js │ │ ├── angular-locale_shi-latn.js │ │ ├── angular-locale_shi-tfng-ma.js │ │ ├── angular-locale_shi-tfng.js │ │ ├── angular-locale_shi.js │ │ ├── angular-locale_si-lk.js │ │ ├── angular-locale_si.js │ │ ├── angular-locale_sk-sk.js │ │ ├── angular-locale_sk.js │ │ ├── angular-locale_sl-si.js │ │ ├── angular-locale_sl.js │ │ ├── angular-locale_smn-fi.js │ │ ├── angular-locale_smn.js │ │ ├── angular-locale_sn-zw.js │ │ ├── angular-locale_sn.js │ │ ├── angular-locale_so-dj.js │ │ ├── angular-locale_so-et.js │ │ ├── angular-locale_so-ke.js │ │ ├── angular-locale_so-so.js │ │ ├── angular-locale_so.js │ │ ├── angular-locale_sq-al.js │ │ ├── angular-locale_sq-mk.js │ │ ├── angular-locale_sq-xk.js │ │ ├── angular-locale_sq.js │ │ ├── angular-locale_sr-cyrl-ba.js │ │ ├── angular-locale_sr-cyrl-me.js │ │ ├── angular-locale_sr-cyrl-rs.js │ │ ├── angular-locale_sr-cyrl-xk.js │ │ ├── angular-locale_sr-cyrl.js │ │ ├── angular-locale_sr-latn-ba.js │ │ ├── angular-locale_sr-latn-me.js │ │ ├── angular-locale_sr-latn-rs.js │ │ ├── angular-locale_sr-latn-xk.js │ │ ├── angular-locale_sr-latn.js │ │ ├── angular-locale_sr.js │ │ ├── angular-locale_ss-sz.js │ │ ├── angular-locale_ss-za.js │ │ ├── angular-locale_ss.js │ │ ├── angular-locale_ssy-er.js │ │ ├── angular-locale_ssy.js │ │ ├── angular-locale_st-ls.js │ │ ├── angular-locale_st-za.js │ │ ├── angular-locale_st.js │ │ ├── angular-locale_sv-ax.js │ │ ├── angular-locale_sv-fi.js │ │ ├── angular-locale_sv-se.js │ │ ├── angular-locale_sv.js │ │ ├── angular-locale_sw-ke.js │ │ ├── angular-locale_sw-tz.js │ │ ├── angular-locale_sw-ug.js │ │ ├── angular-locale_sw.js │ │ ├── angular-locale_swc-cd.js │ │ ├── angular-locale_swc.js │ │ ├── angular-locale_ta-in.js │ │ ├── angular-locale_ta-lk.js │ │ ├── angular-locale_ta-my.js │ │ ├── angular-locale_ta-sg.js │ │ ├── angular-locale_ta.js │ │ ├── angular-locale_te-in.js │ │ ├── angular-locale_te.js │ │ ├── angular-locale_teo-ke.js │ │ ├── angular-locale_teo-ug.js │ │ ├── angular-locale_teo.js │ │ ├── angular-locale_tg-cyrl-tj.js │ │ ├── angular-locale_tg-cyrl.js │ │ ├── angular-locale_tg.js │ │ ├── angular-locale_th-th.js │ │ ├── angular-locale_th.js │ │ ├── angular-locale_ti-er.js │ │ ├── angular-locale_ti-et.js │ │ ├── angular-locale_ti.js │ │ ├── angular-locale_tig-er.js │ │ ├── angular-locale_tig.js │ │ ├── angular-locale_tl.js │ │ ├── angular-locale_tn-bw.js │ │ ├── angular-locale_tn-za.js │ │ ├── angular-locale_tn.js │ │ ├── angular-locale_to-to.js │ │ ├── angular-locale_to.js │ │ ├── angular-locale_tr-cy.js │ │ ├── angular-locale_tr-tr.js │ │ ├── angular-locale_tr.js │ │ ├── angular-locale_ts-za.js │ │ ├── angular-locale_ts.js │ │ ├── angular-locale_twq-ne.js │ │ ├── angular-locale_twq.js │ │ ├── angular-locale_tzm-latn-ma.js │ │ ├── angular-locale_tzm-latn.js │ │ ├── angular-locale_tzm.js │ │ ├── angular-locale_ug-arab-cn.js │ │ ├── angular-locale_ug-arab.js │ │ ├── angular-locale_ug.js │ │ ├── angular-locale_uk-ua.js │ │ ├── angular-locale_uk.js │ │ ├── angular-locale_ur-in.js │ │ ├── angular-locale_ur-pk.js │ │ ├── angular-locale_ur.js │ │ ├── angular-locale_uz-arab-af.js │ │ ├── angular-locale_uz-arab.js │ │ ├── angular-locale_uz-cyrl-uz.js │ │ ├── angular-locale_uz-cyrl.js │ │ ├── angular-locale_uz-latn-uz.js │ │ ├── angular-locale_uz-latn.js │ │ ├── angular-locale_uz.js │ │ ├── angular-locale_vai-latn-lr.js │ │ ├── angular-locale_vai-latn.js │ │ ├── angular-locale_vai-vaii-lr.js │ │ ├── angular-locale_vai-vaii.js │ │ ├── angular-locale_vai.js │ │ ├── angular-locale_ve-za.js │ │ ├── angular-locale_ve.js │ │ ├── angular-locale_vi-vn.js │ │ ├── angular-locale_vi.js │ │ ├── angular-locale_vo-001.js │ │ ├── angular-locale_vo.js │ │ ├── angular-locale_vun-tz.js │ │ ├── angular-locale_vun.js │ │ ├── angular-locale_wae-ch.js │ │ ├── angular-locale_wae.js │ │ ├── angular-locale_wal-et.js │ │ ├── angular-locale_wal.js │ │ ├── angular-locale_xh-za.js │ │ ├── angular-locale_xh.js │ │ ├── angular-locale_xog-ug.js │ │ ├── angular-locale_xog.js │ │ ├── angular-locale_yav-cm.js │ │ ├── angular-locale_yav.js │ │ ├── angular-locale_yi-001.js │ │ ├── angular-locale_yi.js │ │ ├── angular-locale_yo-bj.js │ │ ├── angular-locale_yo-ng.js │ │ ├── angular-locale_yo.js │ │ ├── angular-locale_zgh-ma.js │ │ ├── angular-locale_zgh.js │ │ ├── angular-locale_zh-cn.js │ │ ├── angular-locale_zh-hans-cn.js │ │ ├── angular-locale_zh-hans-hk.js │ │ ├── angular-locale_zh-hans-mo.js │ │ ├── angular-locale_zh-hans-sg.js │ │ ├── angular-locale_zh-hans.js │ │ ├── angular-locale_zh-hant-hk.js │ │ ├── angular-locale_zh-hant-mo.js │ │ ├── angular-locale_zh-hant-tw.js │ │ ├── angular-locale_zh-hant.js │ │ ├── angular-locale_zh-hk.js │ │ ├── angular-locale_zh-tw.js │ │ ├── angular-locale_zh.js │ │ ├── angular-locale_zu-za.js │ │ └── angular-locale_zu.js │ ├── jquery-2.1.3.intellisense.js │ ├── jquery-2.1.3.js │ ├── jquery-2.1.3.min.js │ ├── jquery-2.1.3.min.map │ ├── modernizr-2.8.3.js │ ├── npm.js │ ├── respond.js │ ├── respond.matchmedia.addListener.js │ ├── respond.matchmedia.addListener.min.js │ ├── respond.min.js │ ├── toastr.js │ ├── toastr.min.js │ └── version.json ├── Spa.csproj ├── Views │ ├── Spa │ │ └── Index.cshtml │ └── web.config ├── Web.Debug.config ├── Web.Release.config ├── Web.config ├── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.svg │ ├── glyphicons-halflings-regular.ttf │ ├── glyphicons-halflings-regular.woff │ └── glyphicons-halflings-regular.woff2 ├── packages.config └── spa │ ├── app.js │ ├── common │ ├── common.module.js │ ├── utilityService.js │ └── validation │ │ ├── skAsyncValidators.js │ │ ├── skHasError.js │ │ ├── skMatch.js │ │ └── skUnique.js │ ├── content │ ├── content.module.js │ ├── features │ │ ├── FeaturesController.js │ │ └── features.html │ └── welcome │ │ ├── WelcomeController.js │ │ └── welcome.html │ ├── core │ ├── appActivityService.js │ ├── appStatusService.js │ ├── core.module.js │ ├── navigationService.js │ ├── notifierService.js │ ├── skAppReady.js │ ├── skDisableWhenBusy.js │ ├── skFocusOnSetPristine.js │ └── storageService.js │ └── shell │ ├── ShellController.js │ ├── shell.html │ ├── shell.module.js │ ├── skBusyIndicator.html │ ├── skBusyIndicator.js │ ├── skLoadingScreen.html │ ├── skLoadingScreen.js │ ├── skNavLink.html │ ├── skNavLink.js │ ├── skNavLinks.html │ ├── skNavLinks.js │ ├── skTopNav.html │ └── skTopNav.js └── readme.md /License.txt: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | 4 | Copyright (c) 2014 Useful Software Solutions Ltd 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | 14 | The above copyright notice and this permission notice shall be included in 15 | all copies or substantial portions of the Software. 16 | 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | THE SOFTWARE. -------------------------------------------------------------------------------- /Nuget/MakeAll.bat: -------------------------------------------------------------------------------- 1 | call Spa\CreatePackage.bat 2 | 3 | call Secured.Client\CreatePackage.bat 4 | 5 | call Secured.Server\CreatePackage.bat 6 | 7 | call SecureStarter\CreatePackage.bat -------------------------------------------------------------------------------- /Nuget/SecureStarter/AngularJs.StarterKit.SecureStarter.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Angular.SecureStarter 5 | 2.0.3-alpha 6 | Angular.SecureStarter 7 | JayChase 8 | JayChase 9 | https://github.com/Useful-Software-Solutions-Ltd/Angular.Net.SecureStarter/blob/master/License.txt 10 | https://github.com/Useful-Software-Solutions-Ltd/Angular.Net.SecureStarter 11 | false 12 | An Angular starter kit secured with ASP.NET Identity/OAuth 13 | An Angular starter kit with authentication (ASP.NET Identity 2.1.0). To get started create a new empty web application, then install the package. To use build and run the application then navigate to http://your-url/spa. For more information please see the wiki on the project site. 14 | 15 | Copyright 2015 Useful Software Solutions Ltd 16 | angularjs angular spa authentication OAuth OWIN "ASP.NET Identity" 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Nuget/SecureStarter/CreatePackage.bat: -------------------------------------------------------------------------------- 1 | ::make sure nuget is up to date 2 | 3 | ::nuget Update -self 4 | 5 | SET sourceDir=Secured 6 | SET destinationDir=SecureStarter\content 7 | 8 | ::Clear any existing content files 9 | RMDIR %destinationDir% /S /Q 10 | 11 | ::clear any existing packages from this folder 12 | DEL Angular.SecureStarter.*.nupkg /F /Q 13 | 14 | ::sort out the namespace in cs files 15 | 16 | ::PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& 'C:\Work\AwesomeWeb\Angular.Net.SecureStarter\Nuget\SecureStarter\transformations.ps1'" 17 | 18 | ::create the nuget package 19 | nuget pack SecureStarter\AngularJs.StarterKit.SecureStarter.nuspec 20 | 21 | DEL C:\Users\Jon\Documents\USS Work\LocalNuget\Angular.SecureStarter.*.nupkg /F /Q 22 | 23 | echo F | xcopy /Y Angular.SecureStarter.*.nupkg "C:\Users\Jon\Documents\USS Work\LocalNuget\Angular.SecureStarter.*.nupkg" -------------------------------------------------------------------------------- /Nuget/Secured.Client/AngularJs.StarterKit.Spa.Secured.Client.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | AngularJs.StarterKit.Spa.Secured.Client 5 | 2.0.3-alpha 6 | AngularJS starter kit Spa Secured client 7 | JayChase 8 | JayChase 9 | https://github.com/Useful-Software-Solutions-Ltd/Angular.Net.SecureStarter/blob/master/License.txt 10 | https://github.com/Useful-Software-Solutions-Ltd/Angular.Net.SecureStarter 11 | false 12 | AngularJS starter kit Spa secured client 13 | AngularJS starter kit Spa secured client 14 | 15 | Copyright 2015 Useful Software Solutions Ltd 16 | angularjs angular spa authentication OAuth OWIN "ASP.NET Identity" 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Nuget/Secured.Client/CreatePackage.bat: -------------------------------------------------------------------------------- 1 | ::make sure nuget is up to date 2 | 3 | ::nuget Update -self 4 | 5 | SET sourceDir=Secured 6 | SET destinationDir=Secured.Client\content 7 | 8 | ::Clear any existing content files 9 | RMDIR %destinationDir% /S /Q 10 | 11 | ::clear any existing packages from this folder 12 | DEL AngularJs.StarterKit.spa.secured.client.*.nupkg /F /Q 13 | 14 | ::copy source files 15 | 16 | echo D | xcopy /Y /E ..\%sourceDir%\spa\security %destinationDir%\spa\security 17 | echo F | xcopy /Y ..\%sourceDir%\spa\app.js %destinationDir%\spa\app.js 18 | echo F | xcopy /Y ..\%sourceDir%\spa\shell\skTopNav.* %destinationDir%\spa\shell\skTopNav.* 19 | 20 | echo F | xcopy /Y ..\%sourceDir%\spa\content\SecuredWebapiDemo\*.* %destinationDir%\spa\content\SecuredWebapiDemo\*.* 21 | echo F | xcopy /Y ..\%sourceDir%\spa\content\content.module.js %destinationDir%\spa\content\content.module.js 22 | 23 | echo F | xcopy /Y ..\%sourceDir%\App_Start\SecuredClientBundleConfig.cs "%destinationDir%\App_Start\SecuredClientBundleConfig.cs.pp" 24 | 25 | echo F | xcopy /Y ..\%sourceDir%\Controllers\SecuredController.cs "%destinationDir%\Controllers\SecuredController.cs.pp" 26 | 27 | echo F | xcopy /Y ..\%sourceDir%\Views\Spa\Index.cshtml "%destinationDir%\Views\Spa\Index.cshtml" 28 | 29 | ::sort out the namespace in cs files 30 | 31 | PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& 'C:\Work\AwesomeWeb\Angular.Net.SecureStarter\Nuget\secured.client\transformations.ps1'" 32 | 33 | ::create the nuget package 34 | nuget pack secured.client\AngularJs.StarterKit.spa.secured.client.nuspec 35 | 36 | DEL C:\Users\Jon\Documents\USS Work\LocalNuget\AngularJs.StarterKit.spa.secured.client.*.nupkg /F /Q 37 | 38 | echo F | xcopy /Y AngularJs.StarterKit.spa.secured.client.*.nupkg "C:\Users\Jon\Documents\USS Work\LocalNuget\AngularJs.StarterKit.spa.secured.client.*.nupkg" -------------------------------------------------------------------------------- /Nuget/Secured.Client/tools/install.ps1: -------------------------------------------------------------------------------- 1 | param($installPath, $toolsPath, $package, $project) 2 | 3 | $path = [System.IO.Path] 4 | $readmefile = $path::Combine($path::GetDirectoryName($project.FileName), "readme.md") 5 | $DTE.ItemOperations.Navigate("https://github.com/Useful-Software-Solutions-Ltd/Angular.Net.SecureStarter/wiki") -------------------------------------------------------------------------------- /Nuget/Secured.Client/transformations.ps1: -------------------------------------------------------------------------------- 1 | $Files = Get-ChildItem ".\Secured.Client\content\*.pp" -recurse -force 2 | Foreach ($File in $Files) 3 | { 4 | (get-content $File) | foreach-object {$_ -replace "namespace Secured", 'namespace $rootnamespace$' -replace "using Secured", 'using $rootnamespace$' -replace "Secured.WebApiApplication", '$rootnamespace$.WebApiApplication' -replace 'Secured.App_Start','$rootnamespace$.App_Start' -replace 'namespace="Secured"','namespace="$rootnamespace$"' -replace "\[RequireHttps\]", ''} | set-content $File 5 | } -------------------------------------------------------------------------------- /Nuget/Secured.Server/AngularJs.StarterKit.Spa.Secured.Server.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | AngularJs.StarterKit.Spa.Secured.Server 5 | 2.0.3-alpha 6 | AngularJS starter kit Spa Secured server 7 | JayChase 8 | JayChase 9 | https://github.com/Useful-Software-Solutions-Ltd/Angular.Net.SecureStarter/blob/master/License.txt 10 | https://github.com/Useful-Software-Solutions-Ltd/Angular.Net.SecureStarter 11 | false 12 | AngularJS starter kit Spa secured server 13 | AngularJS starter kit Spa secured server 14 | 15 | Copyright 2015 Useful Software Solutions Ltd 16 | angularjs angular spa authentication OAuth OWIN "ASP.NET Identity" 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /Nuget/Secured.Server/tools/install.ps1: -------------------------------------------------------------------------------- 1 | param($installPath, $toolsPath, $package, $project) 2 | 3 | $path = [System.IO.Path] 4 | #not working yet delete empty.txt marker file after install 5 | $appData = $path::Combine($path::GetDirectoryName($project.FileName), "App_Data") 6 | Write-Host "hello" 7 | #Write-Host $emptyFile 8 | New-Item -ItemType directory -Path $appData 9 | 10 | $readmefile = $path::Combine($path::GetDirectoryName($project.FileName), "readme.md") 11 | $DTE.ItemOperations.Navigate("https://github.com/Useful-Software-Solutions-Ltd/Angular.Net.SecureStarter/wiki") -------------------------------------------------------------------------------- /Nuget/Secured.Server/transformations.ps1: -------------------------------------------------------------------------------- 1 | $Files = Get-ChildItem ".\Secured.Server\content\*.pp" -recurse -force 2 | Foreach ($File in $Files) 3 | { 4 | (get-content $File -Raw) | foreach-object {$_ -replace "namespace Secured", 'namespace $rootnamespace$' -replace "using Secured", 'using $rootnamespace$' -replace "Secured.WebApiApplication", '$rootnamespace$.WebApiApplication' -replace 'Secured.App_Start','$rootnamespace$.App_Start' -replace 'namespace="Secured"','namespace="$rootnamespace$"' -replace 'Secured.Startup','$rootnamespace$.Startup' -replace "\[RequireHttps\]", '' -replace "(?ms)^\s+#region ExcludeFromPackage.*?#endregion", ''} | set-content $File 5 | } -------------------------------------------------------------------------------- /Nuget/Spa/AngularJs.StarterKit.Spa.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | AngularJs.StarterKit.Spa 5 | 2.0.3-alpha 6 | AngularJS starter kit Spa 7 | JayChase 8 | JayChase 9 | https://github.com/Useful-Software-Solutions-Ltd/Angular.Net.SecureStarter/blob/master/License.txt 10 | https://github.com/Useful-Software-Solutions-Ltd/Angular.Net.SecureStarter 11 | false 12 | AngularJS starter kit Spa 13 | AngularJS starter kit Spa 14 | 15 | Copyright 2015 Useful Software Solutions Ltd 16 | angularjs angular spa authentication OAuth OWIN "ASP.NET Identity" 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /Nuget/Spa/CreatePackage.bat: -------------------------------------------------------------------------------- 1 | ::make sure nuget is up to date 2 | 3 | ::nuget Update -self 4 | 5 | SET sourceDir=Spa 6 | SET destinationDir=Spa\content 7 | 8 | ::Clear any existing content files 9 | RMDIR %destinationDir% /S /Q 10 | 11 | ::clear any existing packages from this folder 12 | DEL AngularJs.StarterKit.Spa.*.nupkg /F /Q 13 | 14 | ::copy source files 15 | 16 | echo D | xcopy /Y /E ..\%sourceDir%\spa %destinationDir%\spa 17 | 18 | echo F | xcopy /Y ..\%sourceDir%\App_Start\SpaBundleConfig.cs "%destinationDir%\App_Start\SpaBundleConfig.cs.pp" 19 | echo F | xcopy /Y ..\%sourceDir%\App_Start\SpaRouteConfig.cs "%destinationDir%\App_Start\SpaRouteConfig.cs.pp" 20 | 21 | echo F | xcopy /Y ..\%sourceDir%\Content\spa.css "%destinationDir%\Content\spa.css" 22 | echo F | xcopy /Y ..\%sourceDir%\Content\fadeAnimation.css "%destinationDir%\Content\fadeAnimation.css" 23 | 24 | echo F | xcopy /Y ..\%sourceDir%\Controllers\SpaController.cs "%destinationDir%\Controllers\SpaController.cs.pp" 25 | echo F | xcopy /Y ..\%sourceDir%\Views\Spa\Index.cshtml "%destinationDir%\Views\Spa\Index.cshtml" 26 | echo F | xcopy /Y ..\%sourceDir%\Views\web.config "%destinationDir%\Views\web.config.pp" 27 | 28 | ::sort out the namespace in cs files 29 | 30 | PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& 'C:\Work\AwesomeWeb\Angular.Net.SecureStarter\Nuget\Spa\transformations.ps1'" 31 | 32 | ::create the nuget package 33 | nuget pack spa\AngularJs.StarterKit.spa.nuspec 34 | 35 | DEL C:\Users\Jon\Documents\USS Work\LocalNuget\AngularJs.StarterKit.spa.*.nupkg /F /Q 36 | 37 | echo F | xcopy /Y AngularJs.StarterKit.spa.*.nupkg "C:\Users\Jon\Documents\USS Work\LocalNuget\AngularJs.StarterKit.spa.*.nupkg" -------------------------------------------------------------------------------- /Nuget/Spa/tools/install.ps1: -------------------------------------------------------------------------------- 1 | param($installPath, $toolsPath, $package, $project) 2 | 3 | $path = [System.IO.Path] 4 | $readmefile = $path::Combine($path::GetDirectoryName($project.FileName), "readme.md") 5 | $DTE.ItemOperations.Navigate("https://github.com/Useful-Software-Solutions-Ltd/Angular.Net.SecureStarter/wiki") -------------------------------------------------------------------------------- /Nuget/Spa/transformations.ps1: -------------------------------------------------------------------------------- 1 | $Files = Get-ChildItem ".\spa\content\*.pp" -recurse -force 2 | Foreach ($File in $Files) 3 | { 4 | (get-content $File) | foreach-object {$_ -replace "namespace Spa", 'namespace $rootnamespace$' -replace "using Spa", 'using $rootnamespace$' -replace "Spa.WebApiApplication", '$rootnamespace$.WebApiApplication' -replace 'Spa.App_Start','$rootnamespace$.App_Start' -replace 'namespace="Spa"','namespace="$rootnamespace$"' -replace "\[RequireHttps\]", ''} | set-content $File 5 | } -------------------------------------------------------------------------------- /Secured/App_Start/SecuredServerStartup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Microsoft.Owin; 5 | using Owin; 6 | 7 | [assembly: OwinStartup(typeof(Secured.Startup))] 8 | namespace Secured 9 | { 10 | public partial class Startup 11 | { 12 | public void Configuration(IAppBuilder app) 13 | { 14 | ConfigureAuth(app); 15 | } 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /Secured/App_Start/SecuredServerWebApiConfig.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Owin.Security.OAuth; 2 | using Newtonsoft.Json.Serialization; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Web; 7 | using System.Web.Http; 8 | using System.Web.Http.Routing; 9 | using System.Web.Mvc; 10 | using System.Web.Routing; 11 | 12 | [assembly: WebActivatorEx.PostApplicationStartMethod(typeof(Secured.App_Start.SecuredServerWebApiConfig), "Start")] 13 | namespace Secured.App_Start 14 | { 15 | 16 | public class SecuredServerWebApiConfig 17 | { 18 | 19 | public static void Start() 20 | { 21 | GlobalConfiguration.Configure(Register); 22 | } 23 | 24 | 25 | public static void Register(HttpConfiguration config) 26 | { 27 | 28 | // Web API configuration and services 29 | // Configure Web API to use only bearer token authentication. 30 | config.SuppressDefaultHostAuthentication(); 31 | 32 | config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType)); 33 | 34 | // Use camel case for JSON data. 35 | config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); 36 | 37 | // If MapHttpAttributeRoutes has not been called then do so now 38 | IHttpRoute attributerouteWebApiRoute; 39 | config.Routes.TryGetValue("MS_attributerouteWebApi", out attributerouteWebApiRoute); 40 | 41 | if (attributerouteWebApiRoute == null) 42 | { 43 | config.MapHttpAttributeRoutes(); 44 | } 45 | 46 | // If default api route has not been added then do so now 47 | IHttpRoute defaultApiRoute; 48 | config.Routes.TryGetValue("DefaultApi", out defaultApiRoute); 49 | 50 | if (defaultApiRoute == null) 51 | { 52 | config.Routes.MapHttpRoute( 53 | name: "DefaultApi", 54 | routeTemplate: "api/{controller}/{id}", 55 | defaults: new { id = RouteParameter.Optional } 56 | ); 57 | } 58 | } 59 | } 60 | } 61 | 62 | 63 | -------------------------------------------------------------------------------- /Secured/App_Start/SpaRouteConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using System.Web.Routing; 7 | 8 | [assembly: WebActivatorEx.PreApplicationStartMethod(typeof(Secured.App_Start.SpaRouteConfig), "RegisterRoutes")] 9 | namespace Secured.App_Start 10 | { 11 | 12 | public class SpaRouteConfig 13 | { 14 | public static void RegisterRoutes() 15 | { 16 | var routes = RouteTable.Routes; 17 | 18 | //will stop mvc trying to route to thr physical app folder 19 | routes.RouteExistingFiles = true; 20 | 21 | routes.MapRoute( 22 | name: "Spa", 23 | url: "spa/{*all}", 24 | defaults: new { controller = "spa", action = "Index", id = UrlParameter.Optional }); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Secured/Content/fadeAnimation.css: -------------------------------------------------------------------------------- 1 | .fade-animation.ng-leave{-moz-transition:.2s ease-in all;-o-transition:.2s ease-in all;-webkit-transition:.2s ease-in all;transition:.2s ease-in all;opacity:1}.fade-animation.ng-leave.ng-leave-active{opacity:0}.fade-animation.ng-enter{-moz-transition:.2s ease-in all .2s;-o-transition:.2s ease-in all .2s;-webkit-transition:.2s ease-in all .2s;transition:.2s ease-in all .2s;opacity:0}.fade-animation.ng-enter.ng-enter-active{opacity:1} -------------------------------------------------------------------------------- /Secured/Content/spa.css: -------------------------------------------------------------------------------- 1 | #sk-busy-indicator{height:20px;width:20px;padding:0}.spinner-small{-webkit-animation:rotation .6s infinite linear;-moz-animation:rotation .6s infinite linear;-o-animation:rotation .6s infinite linear;animation:rotation .6s infinite linear;border-left:3px solid rgba(0,0,0,.15);border-right:3px solid rgba(0,0,0,.15);border-bottom:3px solid rgba(0,0,0,.15);border-top:3px solid rgba(0,0,0,.8)}.spinner-large-container{margin-top:50px;margin-bottom:50px}.spinner-large{-webkit-animation:rotation 1.5s infinite linear;-moz-animation:rotation 1.5s infinite linear;-o-animation:rotation 1.5s infinite linear;animation:rotation 1.5s infinite linear;border-left:6px solid gray;border-right:6px solid gray;border-bottom:6px solid gray;border-top:6px solid #fff;height:50px;width:50px}.spinner{height:100%;width:100%;margin:0 auto;position:relative;border-radius:100%}@-webkit-keyframes rotation{from{-webkit-transform:rotate(0deg)}to{-webkit-transform:rotate(359deg)}}@-moz-keyframes rotation{from{-moz-transform:rotate(0deg)}to{-moz-transform:rotate(359deg)}}@-o-keyframes rotation{from{-o-transform:rotate(0deg);}to{-o-transform:rotate(359deg);}}@keyframes rotation{from{transform:rotate(0deg)}to{transform:rotate(359deg)}} -------------------------------------------------------------------------------- /Secured/Controllers/SecuredController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net; 5 | using System.Net.Http; 6 | using System.Web.Http; 7 | 8 | namespace Secured.Controllers 9 | { 10 | [Authorize] 11 | public class SecuredController : ApiController 12 | { 13 | // GET: api/Secured 14 | public IEnumerable Get() 15 | { 16 | return new string[] { "value1", "value2" }; 17 | } 18 | 19 | // GET: api/Secured/5 20 | public string Get(int id) 21 | { 22 | return "value"; 23 | } 24 | 25 | // POST: api/Secured 26 | public void Post([FromBody]string value) 27 | { 28 | } 29 | 30 | // PUT: api/Secured/5 31 | public void Put(int id, [FromBody]string value) 32 | { 33 | } 34 | 35 | // DELETE: api/Secured/5 36 | public void Delete(int id) 37 | { 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Secured/Controllers/SpaController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | 7 | namespace Secured.Controllers 8 | { 9 | public class SpaController : Controller 10 | { 11 | public ActionResult Index() 12 | { 13 | return View(); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Secured/Filters/RequireHttpsAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net.Http; 5 | using System.Web; 6 | using System.Web.Http.Controllers; 7 | using System.Web.Http.Filters; 8 | 9 | namespace Secured.Filters 10 | { 11 | public class RequireHttpsAttribute : AuthorizationFilterAttribute 12 | { 13 | public override void OnAuthorization(HttpActionContext actionContext) 14 | { 15 | if (actionContext.Request.RequestUri.Scheme != Uri.UriSchemeHttps) 16 | { 17 | actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.Forbidden) 18 | { 19 | ReasonPhrase = "HTTPS Required" 20 | }; 21 | } 22 | else 23 | { 24 | base.OnAuthorization(actionContext); 25 | } 26 | } 27 | } 28 | } 29 | 30 | -------------------------------------------------------------------------------- /Secured/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JayChase/Angular.Net.SecureStarter/f4ef56b342be9c1aee55990e0b4431e0cc8c8626/Secured/Icon.png -------------------------------------------------------------------------------- /Secured/Models/AccountViewModels.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | 5 | namespace Secured.Models 6 | { 7 | // Models returned by AccountController actions. 8 | public class ExternalLoginViewModel 9 | { 10 | public string Name { get; set; } 11 | 12 | public string Url { get; set; } 13 | 14 | public string State { get; set; } 15 | } 16 | 17 | public class LoginViewModel 18 | { 19 | [Required] 20 | public string Id { get; set; } //username or email 21 | 22 | [Required] 23 | public string Password { get; set; } 24 | 25 | public bool Remember { get; set; } 26 | } 27 | 28 | public class ManageInfoViewModel 29 | { 30 | public string LocalLoginProvider { get; set; } 31 | 32 | public string Email { get; set; } 33 | 34 | public string UserName { get; set; } 35 | 36 | public IEnumerable Logins { get; set; } 37 | 38 | public IEnumerable ExternalLoginProviders { get; set; } 39 | } 40 | 41 | public class UserInfoViewModel 42 | { 43 | public string UserName { get; set; } 44 | 45 | public string Email { get; set; } 46 | 47 | public bool HasRegistered { get; set; } 48 | 49 | public string LoginProvider { get; set; } 50 | 51 | public string UserRoles { get; set; } 52 | } 53 | 54 | public class UserLoginInfoViewModel 55 | { 56 | public string LoginProvider { get; set; } 57 | 58 | public string ProviderKey { get; set; } 59 | } 60 | } 61 | 62 | 63 | -------------------------------------------------------------------------------- /Secured/Models/ApplicationDbInitializer.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNet.Identity.EntityFramework; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Data.Entity; 5 | using System.Linq; 6 | using System.Web; 7 | using System.Web.Helpers; 8 | 9 | namespace Secured.Models 10 | { 11 | public class ApplicationDbInitializer: CreateDatabaseIfNotExists 12 | { 13 | protected override void Seed(ApplicationDbContext context) 14 | { 15 | var adminRole = new IdentityRole { Name = "administrator" }; 16 | var userRole = new IdentityRole { Name = "user" }; 17 | 18 | context.Roles.Add(adminRole); 19 | context.Roles.Add(userRole); 20 | 21 | var hash = Crypto.HashPassword("Administrator55$"); 22 | 23 | var adminUser = new ApplicationUser { UserName = "Administrator", Email = "Administrator@acme.com", SecurityStamp="dummyStamp", PasswordHash = hash }; 24 | 25 | context.Users.Add(adminUser); 26 | 27 | context.SaveChanges(); 28 | 29 | adminUser.Roles.Add(new IdentityUserRole { UserId = adminUser.Id, RoleId = adminRole.Id }); 30 | adminUser.Roles.Add(new IdentityUserRole { UserId = adminUser.Id, RoleId = userRole.Id }); 31 | } 32 | } 33 | } 34 | 35 | 36 | -------------------------------------------------------------------------------- /Secured/Models/IdentityModels.cs: -------------------------------------------------------------------------------- 1 | using System.Security.Claims; 2 | using System.Threading.Tasks; 3 | using Microsoft.AspNet.Identity; 4 | using Microsoft.AspNet.Identity.EntityFramework; 5 | using Microsoft.AspNet.Identity.Owin; 6 | using System.Data.Entity; 7 | 8 | namespace Secured.Models 9 | { 10 | // You can add profile data for the user by adding more properties to your ApplicationUser class, please visit http://go.microsoft.com/fwlink/?LinkID=317594 to learn more. 11 | public class ApplicationUser : IdentityUser 12 | { 13 | public async Task GenerateUserIdentityAsync(UserManager manager, string authenticationType) 14 | { 15 | // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType 16 | var userIdentity = await manager.CreateIdentityAsync(this, authenticationType); 17 | // Add custom user claims here 18 | return userIdentity; 19 | } 20 | } 21 | 22 | public class ApplicationDbContext : IdentityDbContext 23 | { 24 | public ApplicationDbContext() 25 | : base("AuthConnection", throwIfV1Schema: false) 26 | { 27 | } 28 | 29 | public static ApplicationDbContext Create() 30 | { 31 | var context = new ApplicationDbContext(); 32 | Database.SetInitializer(new ApplicationDbInitializer()); 33 | return context; 34 | } 35 | } 36 | } 37 | 38 | -------------------------------------------------------------------------------- /Secured/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Secured")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Secured")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("2beee4ea-faf3-4e12-ab5f-cc8c23b545df")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /Secured/Results/ChallengeResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net; 5 | using System.Net.Http; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | using System.Web.Http; 9 | 10 | namespace Secured.Results 11 | { 12 | public class ChallengeResult : IHttpActionResult 13 | { 14 | public ChallengeResult(string loginProvider, ApiController controller) 15 | { 16 | LoginProvider = loginProvider; 17 | Request = controller.Request; 18 | } 19 | 20 | public string LoginProvider { get; set; } 21 | public HttpRequestMessage Request { get; set; } 22 | 23 | public Task ExecuteAsync(CancellationToken cancellationToken) 24 | { 25 | Request.GetOwinContext().Authentication.Challenge(LoginProvider); 26 | 27 | HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.Unauthorized); 28 | response.RequestMessage = Request; 29 | return Task.FromResult(response); 30 | } 31 | } 32 | } 33 | 34 | -------------------------------------------------------------------------------- /Secured/Scripts/angular-cookies.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | AngularJS v1.3.15 3 | (c) 2010-2014 Google, Inc. http://angularjs.org 4 | License: MIT 5 | */ 6 | (function(p,f,n){'use strict';f.module("ngCookies",["ng"]).factory("$cookies",["$rootScope","$browser",function(e,b){var c={},g={},h,k=!1,l=f.copy,m=f.isUndefined;b.addPollFn(function(){var a=b.cookies();h!=a&&(h=a,l(a,g),l(a,c),k&&e.$apply())})();k=!0;e.$watch(function(){var a,d,e;for(a in g)m(c[a])&&b.cookies(a,n);for(a in c)d=c[a],f.isString(d)||(d=""+d,c[a]=d),d!==g[a]&&(b.cookies(a,d),e=!0);if(e)for(a in d=b.cookies(),c)c[a]!==d[a]&&(m(d[a])?delete c[a]:c[a]=d[a])});return c}]).factory("$cookieStore", 7 | ["$cookies",function(e){return{get:function(b){return(b=e[b])?f.fromJson(b):b},put:function(b,c){e[b]=f.toJson(c)},remove:function(b){delete e[b]}}}])})(window,window.angular); 8 | //# sourceMappingURL=angular-cookies.min.js.map 9 | -------------------------------------------------------------------------------- /Secured/Scripts/angular-cookies.min.js.map: -------------------------------------------------------------------------------- 1 | { 2 | "version":3, 3 | "file":"angular-cookies.min.js", 4 | "lineCount":7, 5 | "mappings":"A;;;;;aAKC,SAAQ,CAACA,CAAD,CAASC,CAAT,CAAkBC,CAAlB,CAA6B,CAmBtCD,CAAAE,OAAA,CAAe,WAAf,CAA4B,CAAC,IAAD,CAA5B,CAAAC,QAAA,CA0BW,UA1BX,CA0BuB,CAAC,YAAD,CAAe,UAAf,CAA2B,QAAQ,CAACC,CAAD,CAAaC,CAAb,CAAuB,CAAA,IACvEC,EAAU,EAD6D,CAEvEC,EAAc,EAFyD,CAGvEC,CAHuE,CAIvEC,EAAU,CAAA,CAJ6D,CAKvEC,EAAOV,CAAAU,KALgE,CAMvEC,EAAcX,CAAAW,YAGlBN,EAAAO,UAAA,CAAmB,QAAQ,EAAG,CAC5B,IAAIC,EAAiBR,CAAAC,QAAA,EACjBE,EAAJ,EAA0BK,CAA1B,GACEL,CAGA,CAHqBK,CAGrB,CAFAH,CAAA,CAAKG,CAAL,CAAqBN,CAArB,CAEA,CADAG,CAAA,CAAKG,CAAL,CAAqBP,CAArB,CACA,CAAIG,CAAJ,EAAaL,CAAAU,OAAA,EAJf,CAF4B,CAA9B,CAAA,EAUAL,EAAA,CAAU,CAAA,CAKVL,EAAAW,OAAA,CASAC,QAAa,EAAG,CAAA,IACVC,CADU,CAEVC,CAFU,CAIVC,CAGJ,KAAKF,CAAL,GAAaV,EAAb,CACMI,CAAA,CAAYL,CAAA,CAAQW,CAAR,CAAZ,CAAJ,EACEZ,CAAAC,QAAA,CAAiBW,CAAjB,CAAuBhB,CAAvB,CAKJ,KAAKgB,CAAL,GAAaX,EAAb,CACEY,CAKA,CALQZ,CAAA,CAAQW,CAAR,CAKR,CAJKjB,CAAAoB,SAAA,CAAiBF,CAAjB,CAIL,GAHEA,CACA,CADQ,EACR,CADaA,CACb,CAAAZ,CAAA,CAAQW,CAAR,CAAA,CAAgBC,CAElB,EAAIA,CAAJ,GAAcX,CAAA,CAAYU,CAAZ,CAAd,GACEZ,CAAAC,QAAA,CAAiBW,CAAjB,CAAuBC,CAAvB,CACA,CAAAC,CAAA,CAAU,CAAA,CAFZ,CAOF,IAAIA,CAAJ,CAIE,IAAKF,CAAL,GAFAI,EAEaf,CAFID,CAAAC,QAAA,EAEJA,CAAAA,CAAb,CACMA,CAAA,CAAQW,CAAR,CAAJ,GAAsBI,CAAA,CAAeJ,CAAf,CAAtB,GAEMN,CAAA,CAAYU,CAAA,CAAeJ,CAAf,CAAZ,CAAJ,CACE,OAAOX,CAAA,CAAQW,CAAR,CADT,CAGEX,CAAA,CAAQW,CAAR,CAHF,CAGkBI,CAAA,CAAeJ,CAAf,CALpB,CAhCU,CAThB,CAEA,OAAOX,EA1BoE,CAA1D,CA1BvB,CAAAH,QAAA,CAoIW,cApIX;AAoI2B,CAAC,UAAD,CAAa,QAAQ,CAACmB,CAAD,CAAW,CAErD,MAAO,CAWLC,IAAKA,QAAQ,CAACC,CAAD,CAAM,CAEjB,MAAO,CADHN,CACG,CADKI,CAAA,CAASE,CAAT,CACL,EAAQxB,CAAAyB,SAAA,CAAiBP,CAAjB,CAAR,CAAkCA,CAFxB,CAXd,CA0BLQ,IAAKA,QAAQ,CAACF,CAAD,CAAMN,CAAN,CAAa,CACxBI,CAAA,CAASE,CAAT,CAAA,CAAgBxB,CAAA2B,OAAA,CAAeT,CAAf,CADQ,CA1BrB,CAuCLU,OAAQA,QAAQ,CAACJ,CAAD,CAAM,CACpB,OAAOF,CAAA,CAASE,CAAT,CADa,CAvCjB,CAF8C,CAAhC,CApI3B,CAnBsC,CAArC,CAAD,CAwMGzB,MAxMH,CAwMWA,MAAAC,QAxMX;", 6 | "sources":["angular-cookies.js"], 7 | "names":["window","angular","undefined","module","factory","$rootScope","$browser","cookies","lastCookies","lastBrowserCookies","runEval","copy","isUndefined","addPollFn","currentCookies","$apply","$watch","push","name","value","updated","isString","browserCookies","$cookies","get","key","fromJson","put","toJson","remove"] 8 | } 9 | -------------------------------------------------------------------------------- /Secured/Scripts/angular-csp.css: -------------------------------------------------------------------------------- 1 | /* Include this file in your html if you are using the CSP mode. */ 2 | 3 | @charset "UTF-8"; 4 | 5 | [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], 6 | .ng-cloak, .x-ng-cloak, 7 | .ng-hide:not(.ng-hide-animate) { 8 | display: none !important; 9 | } 10 | 11 | ng\:form { 12 | display: block; 13 | } 14 | -------------------------------------------------------------------------------- /Secured/Scripts/angular-loader.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | AngularJS v1.3.15 3 | (c) 2010-2014 Google, Inc. http://angularjs.org 4 | License: MIT 5 | */ 6 | (function(){'use strict';function d(b){return function(){var c=arguments[0],e;e="["+(b?b+":":"")+c+"] http://errors.angularjs.org/1.3.15/"+(b?b+"/":"")+c;for(c=1;c").html(a);f.forEach(a.children(), 8 | function(a){a=f.element(a);h?h.after(a):d.prepend(a);h=a;q(a)(b)});c.renderMessages(e,g)})}}}]).directive("ngMessage",["$animate",function(f){return{require:"^ngMessages",transclude:"element",terminal:!0,restrict:"AE",link:function(k,l,b,d,a){for(var c,g,e=l[0],n=e.parentNode,h=0,p=0;h 5 | 6 | 7 | 14 | Angular starter kit 15 | 16 | 17 | 18 | 19 | 28 | 29 | @Styles.Render("~/Content/spaCss") 30 | @Scripts.Render("~/bundles/spaModernizr") 31 | 32 | 33 |
34 |
35 | @Scripts.Render("~/bundles/spaVendor") 36 | @Scripts.Render("~/bundles/angular") 37 | @Scripts.Render("~/bundles/securityAngularModules") 38 | @Scripts.Render("~/bundles/common") 39 | @Scripts.Render("~/bundles/content") 40 | @Scripts.Render("~/bundles/shell") 41 | @Scripts.Render("~/bundles/security") 42 | @Scripts.Render("~/bundles/spa") 43 | 44 | 45 | -------------------------------------------------------------------------------- /Secured/Views/web.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /Secured/Web.Debug.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | -------------------------------------------------------------------------------- /Secured/Web.Release.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | -------------------------------------------------------------------------------- /Secured/Web.config.install.xdt: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Secured/Web.config.uninstall.xdt: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Secured/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JayChase/Angular.Net.SecureStarter/f4ef56b342be9c1aee55990e0b4431e0cc8c8626/Secured/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /Secured/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JayChase/Angular.Net.SecureStarter/f4ef56b342be9c1aee55990e0b4431e0cc8c8626/Secured/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /Secured/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JayChase/Angular.Net.SecureStarter/f4ef56b342be9c1aee55990e0b4431e0cc8c8626/Secured/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /Secured/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JayChase/Angular.Net.SecureStarter/f4ef56b342be9c1aee55990e0b4431e0cc8c8626/Secured/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /Secured/spa/app.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | var app = angular.module('app', ['ngRoute', 'ngAnimate', 'app.core', 'app.shell', 'app.content', 'app.security']); 5 | 6 | app.config(['$locationProvider', function ($locationProvider) { 7 | $locationProvider.html5Mode(true); 8 | }]); 9 | 10 | app.run(['$route', function ($route) { 11 | }]); 12 | })(); -------------------------------------------------------------------------------- /Secured/spa/common/common.module.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | var common = angular.module('app.common', []); 5 | })(); -------------------------------------------------------------------------------- /Secured/spa/common/validation/skAsyncValidators.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | angular 5 | .module('app.common') 6 | .directive('skAsyncValidators', skAsyncValidators); 7 | 8 | skAsyncValidators.$inject = ['$parse']; 9 | 10 | function skAsyncValidators($parse) { 11 | var directive = { 12 | require: 'ngModel', 13 | link: link, 14 | restrict: 'A' 15 | }; 16 | 17 | return directive; 18 | 19 | function link(scope, element, attrs, ngModel) { 20 | var asyncValidators = scope.$eval(attrs["skAsyncValidators"]); 21 | 22 | if (asyncValidators) { 23 | angular.extend(ngModel.$asyncValidators, asyncValidators); 24 | } 25 | } 26 | } 27 | })(); -------------------------------------------------------------------------------- /Secured/spa/common/validation/skHasError.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('app.common') 6 | .directive('skHasError', skHasError); 7 | 8 | function skHasError() { 9 | var directive = { 10 | restrict: 'A', 11 | require: 'ngMessages', 12 | link: link 13 | }; 14 | 15 | return directive; 16 | 17 | function link(scope, element, attrs, ngMessages) { 18 | var renderMessages = ngMessages.renderMessages, 19 | hasErrorTarget; 20 | 21 | if (!hasErrorTarget) { 22 | if (attrs.skHasError) { 23 | hasErrorTarget = element.parents('#' + attrs.skHasError); 24 | } else { 25 | hasErrorTarget = element.parent('.form-group'); 26 | } 27 | } 28 | 29 | ngMessages.renderMessages = function (values, multiple, element) { 30 | renderMessages.apply(this, arguments); 31 | 32 | if ($.isEmptyObject(values)) { 33 | hasErrorTarget.removeClass('has-error'); 34 | } else { 35 | hasErrorTarget.addClass('has-error'); 36 | } 37 | }; 38 | } 39 | } 40 | })(); -------------------------------------------------------------------------------- /Secured/spa/common/validation/skMatch.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | angular.module('app.common') 5 | .directive('skMatch', [skMatch]); 6 | 7 | function skMatch() { 8 | var directive = { 9 | restrict: 'A', 10 | require: 'ngModel', 11 | link: link 12 | }; 13 | 14 | return directive; 15 | 16 | function link(scope, element, attrs, ctrl) { 17 | scope.$watchGroup([ 18 | attrs.ngModel, 19 | attrs.skMatch 20 | ], function (newValues) { 21 | ctrl.$setValidity('match', newValues[0] === newValues[1]); 22 | }); 23 | } 24 | } 25 | })(); -------------------------------------------------------------------------------- /Secured/spa/common/validation/skUnique.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | angular 5 | .module('app.common') 6 | .directive('skUnique', skUnique); 7 | 8 | skUnique.$inject = []; 9 | 10 | function skUnique() { 11 | var directive = { 12 | require: 'ngModel', 13 | link: link, 14 | restrict: 'A', 15 | scope: { 16 | skUnique: '&' 17 | } 18 | }; 19 | 20 | return directive; 21 | 22 | function link(scope, element, attrs, ngModel) { 23 | var wrappedValidator = function (mv, vv) { 24 | ngModel.$setValidity('checking', false); 25 | 26 | return scope.skUnique({ value: mv || vv }) 27 | .finally(function () { 28 | ngModel.$setValidity('checking', true); 29 | }); 30 | }; 31 | 32 | ngModel.$asyncValidators.unique = wrappedValidator; 33 | } 34 | } 35 | })(); -------------------------------------------------------------------------------- /Secured/spa/content/SecuredWebapiDemo/securedWebapiDemo.html: -------------------------------------------------------------------------------- 1 | 
2 |
3 |

{{::vm.title}}

4 |

{{::vm.description}}

5 |
    6 |
  • 7 |

    {{kp}}

    8 |
  • 9 |
10 | 11 |

Response

12 |
13 |
14 |
15 |
16 | {{vm.result}} 17 |
18 |
19 |
20 |
-------------------------------------------------------------------------------- /Secured/spa/content/content.module.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | var content = angular.module('app.content', []); 5 | 6 | content.config(['$routeProvider', 'baseUrl', function ($routeProvider, baseUrl) { 7 | $routeProvider.when('/', { 8 | templateUrl: baseUrl + 'content/welcome/welcome.html', 9 | controller: 'WelcomeController', 10 | controllerAs: 'vm', 11 | caseInsensitiveMatch: true 12 | }) 13 | .when('/welcome', { 14 | templateUrl: baseUrl + 'content/welcome/welcome.html', 15 | controller: 'WelcomeController', 16 | controllerAs: 'vm', 17 | caseInsensitiveMatch: true, 18 | showNav: 'welcome' 19 | }) 20 | .when('/features', { 21 | templateUrl: baseUrl +'content/features/features.html', 22 | controller: 'FeaturesController', 23 | controllerAs: 'vm', 24 | caseInsensitiveMatch: true, 25 | showNav: 'features' 26 | }) 27 | .when('/securedWebapiDemo', { 28 | templateUrl: baseUrl + 'content/securedWebapiDemo/securedWebapiDemo.html', 29 | controller: 'SecuredWebapiDemoController', 30 | controllerAs: 'vm', 31 | caseInsensitiveMatch: true, 32 | showNav: 'Secured Web API demo' 33 | }) 34 | .otherwise('/'); 35 | }]); 36 | 37 | })(); -------------------------------------------------------------------------------- /Secured/spa/content/features/FeaturesController.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | angular.module('app.content') 5 | .controller('FeaturesController', FeaturesController); 6 | 7 | FeaturesController.$inject = ['notifierService', 'appActivityService']; 8 | 9 | function FeaturesController(notifierService, appActivityService) { 10 | /* jshint validthis:true */ 11 | var vm = this; 12 | 13 | vm.title = 'features'; 14 | vm.features = []; 15 | 16 | activate(); 17 | 18 | function activate() { 19 | var busy = false, notifierFeature, appActivityFeature, navigationFeature, authorizationFeature; 20 | 21 | notifierFeature = { 22 | name: "notifier service (notifierService)", 23 | description: "Wraps toastr to make creating user info popups from anywhere in your app easy. Click the demo button to send a message.", 24 | demo: function () { 25 | notifierService.show({message: "A message from the notifierService"}); 26 | } 27 | }; 28 | 29 | vm.features.push(notifierFeature); 30 | 31 | appActivityFeature = { 32 | name: "application activity service (appActivityService)", 33 | description: "Allows the app to track whether it is busy or not. Use the busy/idle methods let the app know. Also use the sk-disable-when-busy directive to disable elements whilst the app is busy.", 34 | demo: function () { 35 | if (busy) { 36 | appActivityService.idle("demo"); 37 | busy = false; 38 | } else { 39 | appActivityService.busy("demo"); 40 | busy = true; 41 | } 42 | } 43 | }; 44 | 45 | vm.features.push(appActivityFeature); 46 | 47 | navigationFeature = { 48 | name: "Dynamic navbar links", 49 | description: "Add the property showNav to a route to show it as a link in the navbar. eg showNav: 'linkText'" 50 | }; 51 | 52 | vm.features.push(navigationFeature); 53 | } 54 | } 55 | })(); 56 | -------------------------------------------------------------------------------- /Secured/spa/content/features/features.html: -------------------------------------------------------------------------------- 1 | 
2 |
3 |

{{::vm.title}}

4 |
    5 |
  • 6 |

    {{f.name}}

    7 |

    {{f.description}}

    8 | 9 |
  • 10 |
11 |
12 |
-------------------------------------------------------------------------------- /Secured/spa/content/welcome/WelcomeController.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | angular.module('app.content') 5 | .controller('WelcomeController',WelcomeController); 6 | 7 | function WelcomeController() { 8 | /* jshint validthis:true */ 9 | var vm = this; 10 | 11 | vm.title = 'Angular starter kit'; 12 | 13 | activate(); 14 | 15 | function activate() { } 16 | } 17 | })(); 18 | -------------------------------------------------------------------------------- /Secured/spa/content/welcome/welcome.html: -------------------------------------------------------------------------------- 1 | 
2 |
3 |
4 |

{{::vm.title}}

5 |

6 | A base project with user authentication/authorization and some other bits to make life a bit easier. See the project wiki for more help getting started. 7 |

8 |

9 | wiki 10 |

11 |
12 |
13 |
14 | 15 | -------------------------------------------------------------------------------- /Secured/spa/core/appActivityService.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | var serviceId = 'appActivityService'; 5 | 6 | angular.module('app.core') 7 | .factory(serviceId, ['$rootScope', appActivityService]); 8 | 9 | function appActivityService($rootScope) { 10 | var service = { 11 | busy: busy, 12 | idle: idle, 13 | info:{ 14 | isBusy: false 15 | }, 16 | reset: reset 17 | }; 18 | 19 | var activities = []; 20 | 21 | return service; 22 | 23 | function busy(name) { 24 | if (!name) { 25 | throw {name:'Error', message:'A valid activity name must be provided.'}; 26 | } 27 | 28 | if (!activities[name]) { 29 | activities.push(name); 30 | } 31 | 32 | updateStatus(); 33 | } 34 | 35 | function idle(name) { 36 | if (!name) { 37 | throw { name: 'Error', message: 'A valid activity name must be provided.' }; 38 | } 39 | 40 | if (!activities[name]) { 41 | activities.pop(name); 42 | } 43 | 44 | updateStatus(); 45 | } 46 | 47 | function updateStatus() { 48 | 49 | var newStatus = activities.length > 0; 50 | 51 | if(service.info.isBusy !== newStatus){ 52 | service.info.isBusy = newStatus; 53 | $rootScope.$broadcast("appActivityService:isBusyChanged", { busy: service.info.isBusy }); 54 | } 55 | } 56 | 57 | function reset() { 58 | activities = []; 59 | updateStatus(); 60 | } 61 | } 62 | })(); -------------------------------------------------------------------------------- /Secured/spa/core/appStatusService.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | var serviceId = 'appStatusService'; 5 | 6 | // TODO: replace app with your module name 7 | angular.module('app.core') 8 | .factory(serviceId, ['$q', appStatusService]); 9 | 10 | function appStatusService($q) { 11 | var deferreds = []; 12 | 13 | var service = { 14 | whenReady: whenReady, 15 | info:{ 16 | ready: false 17 | }, 18 | isReady: isReady 19 | }; 20 | 21 | return service; 22 | 23 | function isReady(value) { 24 | if (service.info.ready !== value) { 25 | service.info.ready = value; 26 | 27 | if (service.info.ready) { 28 | resolvePromises(); 29 | } 30 | } 31 | } 32 | 33 | function whenReady() { 34 | var deferred = $q.defer(); 35 | 36 | if (service.info.ready) { 37 | deferred.resolve(); 38 | } else { 39 | deferreds.push(deferred); 40 | } 41 | 42 | return deferred.promise; 43 | } 44 | 45 | function resolvePromises() { 46 | deferreds.forEach(function (deferred) { 47 | deferred.resolve(); 48 | }); 49 | 50 | deferreds.length = 0; 51 | } 52 | } 53 | })(); -------------------------------------------------------------------------------- /Secured/spa/core/core.module.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | var core = angular.module('app.core', ['app.common']); 4 | 5 | core.config(['$provide', function ($provide) { 6 | $provide.constant("baseUrl", ""); //url to the server location of the spa (requires trailing slash) 7 | $provide.constant("siteUrl", angular.element('base')[0].href); //will have trailing slash 8 | }]); 9 | 10 | //if a client_id header is required add the clientId property to the appSettingsService 11 | core.value('appSettingsService', { 12 | brand: 'AngulerStarterKit', 13 | title: 'Angular Starter Kit' 14 | }); 15 | })(); -------------------------------------------------------------------------------- /Secured/spa/core/navigationService.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | var serviceId = 'navigationService'; 5 | 6 | angular.module('app.core') 7 | .factory(serviceId, ['$route',navigationService]); 8 | 9 | function navigationService($route) { 10 | var links = []; 11 | 12 | var service = { 13 | getLinks: getLinks 14 | }; 15 | 16 | createLinks(); 17 | 18 | function createLinks() { 19 | angular.forEach($route.routes, function (route) { 20 | if (route.showNav) { 21 | links.push({ 22 | name: route.showNav, 23 | url: (removeStartSlash(route.navPath) || removeStartSlash(route.originalPath)), 24 | parent: route.parent 25 | }); 26 | } 27 | }); 28 | } 29 | 30 | function getLinks() { 31 | return links; 32 | } 33 | 34 | return service; 35 | 36 | function removeStartSlash(path) { 37 | if (path && path.charAt(0) === '/') { 38 | path = path.substring(1); 39 | } 40 | 41 | return path; 42 | } 43 | } 44 | })(); -------------------------------------------------------------------------------- /Secured/spa/core/notifierService.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | var serviceId = 'notifierService'; 5 | 6 | toastr.options.closeButton = true; 7 | toastr.options.positionClass = 'toast-bottom-right'; 8 | toastr.options.backgroundpositionClass = 'toast-bottom-right'; 9 | toastr.options.timeOut = 800; 10 | toastr.options.fadeOut = 50; 11 | toastr.options.fadeIn = 50; 12 | 13 | var defaults = { 14 | source: "app", 15 | title: "", 16 | message: "no message provided", 17 | detail: "", 18 | type: "info" 19 | }; 20 | 21 | angular.module('app.core') 22 | .factory(serviceId, [notifierService]); 23 | 24 | function notifierService() { 25 | var service = { 26 | show: show, 27 | verbose: true 28 | }; 29 | 30 | return service; 31 | 32 | function show(options) { 33 | var opns = angular.copy(defaults); 34 | 35 | if (typeof options === "string") { 36 | opns.message = options; 37 | } else { 38 | opns = angular.extend(opns, options); 39 | } 40 | 41 | if (service.verbose && opns.detail.length > 0) { 42 | opns.message += " " + opns.detail; 43 | } 44 | 45 | toastr[opns.type](opns.message, opns.title); 46 | } 47 | } 48 | })(); -------------------------------------------------------------------------------- /Secured/spa/core/skAppReady.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular.module('app.core') 5 | .directive('skAppReady', ['appStatusService', skAppReady]); 6 | 7 | function skAppReady(appStatusService) { 8 | 9 | var directive = { 10 | link: link, 11 | restrict: 'A', 12 | scope: { 13 | 14 | } 15 | }; 16 | return directive; 17 | 18 | function link(scope, element, attr) { 19 | appStatusService.isReady(attr.skAppReady); 20 | } 21 | } 22 | 23 | })(); -------------------------------------------------------------------------------- /Secured/spa/core/skDisableWhenBusy.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular.module('app.core') 5 | .directive('skDisableWhenBusy', ['$rootScope', skDisableWhenBusy]); 6 | 7 | function skDisableWhenBusy($rootScope) { 8 | var directive = { 9 | link: link, 10 | restrict: 'A', 11 | scope: { 12 | disableOn: '=' 13 | } 14 | }; 15 | 16 | return directive; 17 | 18 | function link(scope, element, attrs) { 19 | var target = element, 20 | disable = setDisable(scope.disableOn), 21 | busy = false; 22 | 23 | scope.$watch("disableOn", function (value) { 24 | setDisable(value); 25 | updateDisabled(); 26 | }); 27 | 28 | $rootScope.$on("appActivityService:isBusyChanged", function (event, args) { 29 | busy = args.busy; 30 | updateDisabled(); 31 | }); 32 | 33 | function updateDisabled() { 34 | angular.element(target).prop('disabled', disable || busy); 35 | } 36 | 37 | function setDisable(boolArray) { 38 | var result = false; 39 | 40 | if (boolArray) { 41 | boolArray.forEach(function (b) { 42 | if (b) { 43 | result = true; 44 | } 45 | }); 46 | } 47 | 48 | disable = result; 49 | } 50 | } 51 | } 52 | })(); -------------------------------------------------------------------------------- /Secured/spa/core/skFocusOnSetPristine.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('app.core') 6 | .directive('skFocusOnSetPristine', skFocusOnSetPristine); 7 | 8 | 9 | function skFocusOnSetPristine () { 10 | 11 | var directive = { 12 | link: link, 13 | restrict: 'A' 14 | }; 15 | return directive; 16 | 17 | function link(scope, element, attrs) { 18 | //get the parent form element and form on the scope 19 | var formElement = element.parents('form'), 20 | form = scope[formElement.attr('name')], 21 | focusElement = element; 22 | 23 | scope.$watch(function () { 24 | return form.$pristine; 25 | 26 | }, 27 | function (newValue, oldValue) { 28 | if (newValue && !oldValue) { 29 | element.focus(); 30 | } 31 | }); 32 | } 33 | } 34 | 35 | })(); -------------------------------------------------------------------------------- /Secured/spa/core/storageService.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | var serviceId = 'storageService'; 5 | 6 | angular.module('app.core') 7 | .factory(serviceId, ['utilityService', storageService]); 8 | 9 | function storageService(utilityService) { 10 | var service = { 11 | store: store, 12 | retrieve: retrieve, 13 | remove: remove, 14 | clear: clear, 15 | saveSession: saveSession 16 | }; 17 | 18 | return service; 19 | 20 | //key value json (if true: stringify then store) 21 | function store(key, value, persist) { 22 | if (utilityService.exists(value) && utilityService.isObject(value)) { 23 | value = "!!stringified!!" + JSON.stringify(value); 24 | } 25 | 26 | if (persist) { 27 | localStorage.setItem(key,value); 28 | } else { 29 | sessionStorage.setItem(key, value); 30 | 31 | if (utilityService.exists(localStorage.getItem(key))) { 32 | localStorage.removeItem(key); 33 | } 34 | } 35 | } 36 | 37 | //key value json (if true: parse) 38 | function retrieve(key) { 39 | //if key exists in session storage return that if not try to return local 40 | var value; 41 | 42 | value = localStorage.getItem(key); 43 | 44 | if (!value) { 45 | value = sessionStorage.getItem(key); 46 | } 47 | 48 | if (utilityService.exists(value) && value.indexOf("!!stringified!!") > -1) { 49 | value = value.replace("!!stringified!!", ""); 50 | value = JSON.parse(value); 51 | } 52 | 53 | return value; 54 | } 55 | 56 | function remove(key) { 57 | localStorage.removeItem(key); 58 | sessionStorage.removeItem(key); 59 | } 60 | 61 | //sessionOnly only clear the local (persisted) storage 62 | function clear(sessionOnly) { 63 | if (!sessionOnly) { 64 | localStorage.clear(); 65 | } 66 | 67 | sessionStorage.clear(); 68 | } 69 | 70 | function saveSession() { 71 | angular.extend(localStorage, sessionStorage); 72 | } 73 | } 74 | })(); -------------------------------------------------------------------------------- /Secured/spa/security/ExternalSignInController.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | angular.module('app.security') 5 | .controller('ExternalSignInController', ExternalSignInController); 6 | 7 | ExternalSignInController.$inject = ['$window','siteUrl', 'userService', 'notifierService']; 8 | 9 | function ExternalSignInController($window, siteUrl, userService, notifierService) { 10 | /* jshint validthis:true */ 11 | var vm = this; 12 | 13 | vm.title = "external auth providers" 14 | vm.authProviders = undefined; 15 | vm.login = login; 16 | 17 | activate(); 18 | 19 | function activate() { 20 | getAuthProviders(); 21 | } 22 | 23 | function login(url) { 24 | $window.location.href = userService.authServer + url; 25 | } 26 | 27 | function getAuthProviders() { 28 | userService.getExternalLogins({returnUrl: siteUrl + "externalauth/signin"}) 29 | .then( 30 | function (result) { 31 | vm.authProviders = result; 32 | }, 33 | function (result) { 34 | notifierService.show({ message: "error retrieving external logins", type: "error" }); 35 | }); 36 | } 37 | } 38 | })(); 39 | -------------------------------------------------------------------------------- /Secured/spa/security/ManageController.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | angular.module('app.security') 5 | .controller('ManageController', ManageController); 6 | 7 | ManageController.$inject = ['userManagementService']; 8 | 9 | function ManageController(userManagementService) { 10 | /* jshint validthis:true */ 11 | var vm = this; 12 | 13 | vm.title = 'Manage'; 14 | vm.loginProviders = userManagementService.loginProviders; 15 | vm.userLogins = userManagementService.userLogins; 16 | vm.manageInfo = userManagementService.info; 17 | vm.addLogin = userManagementService.addLogin; 18 | vm.removeLogin = userManagementService.removeLogin; 19 | 20 | activate(); 21 | 22 | function activate() { 23 | userManagementService.load(); 24 | } 25 | 26 | } 27 | })(); 28 | -------------------------------------------------------------------------------- /Secured/spa/security/RegisterController.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | angular.module('app.security') 5 | .controller('RegisterController', RegisterController); 6 | 7 | RegisterController.$inject = ['$location', 'notifierService', 'userService']; 8 | 9 | function RegisterController($location, notifierService, userService) { 10 | /* jshint validthis:true */ 11 | var vm = this; 12 | 13 | vm.title = 'register'; 14 | vm.registration = { 15 | email: "", 16 | username: "", 17 | password: "", 18 | confirmPassword: "" 19 | }; 20 | vm.register = register; 21 | vm.checkUsernameAvailable = userService.checkUsernameAvailable; 22 | vm.checkEmailAvailable = userService.checkEmailAvailable; 23 | 24 | function register() { 25 | userService.register(vm.registration) 26 | .then( 27 | function (result) { 28 | //success 29 | notifierService.show({ message: "sucessfully registered", type: "info" }); 30 | signIn(); 31 | }, 32 | function (result) { 33 | notifierService.show({ message: result.error, type: "error" }); 34 | } 35 | ); 36 | } 37 | 38 | function signIn() { 39 | notifierService.show({ message: "signing in", type: "warning" }); 40 | 41 | var user = { 42 | id: vm.registration.email, 43 | password: vm.registration.password 44 | }; 45 | 46 | userService.signIn(user) 47 | .then( 48 | function (result) { 49 | notifierService.show({ message: "signed in as " + userService.info.username, type: "info" }); 50 | $location.path("/"); 51 | }, 52 | function (result) { 53 | notifierService.show({ message: result.error, type: "error" }); 54 | } 55 | ); 56 | } 57 | } 58 | })(); 59 | -------------------------------------------------------------------------------- /Secured/spa/security/SignInController.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | angular.module('app.security') 5 | .controller('SignInController', SignInController); 6 | 7 | SignInController.$inject = ['$scope', '$location', 'userService', 'notifierService']; 8 | 9 | function SignInController($scope, $location, userService, notifierService) { 10 | /* jshint validthis:true */ 11 | var vm = this, 12 | user = { 13 | id: "", 14 | password: "", 15 | remember: false 16 | }; 17 | 18 | vm.title = 'sign in'; 19 | vm.user = angular.copy(user); 20 | vm.signIn = signIn; 21 | vm.result = ""; 22 | 23 | activate(); 24 | 25 | function activate() { 26 | 27 | } 28 | 29 | function signIn() { 30 | 31 | userService.signIn(vm.user) 32 | .then( 33 | function (result) { 34 | $location.path('/'); 35 | }, 36 | function (result) { 37 | vm.user = angular.copy(user); 38 | $scope.signInForm.$setPristine(); 39 | $scope.signInForm.$setUntouched(); 40 | } 41 | ); 42 | } 43 | } 44 | })(); 45 | -------------------------------------------------------------------------------- /Secured/spa/security/clientIdHttpInterceptor.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | var id = 'clientIdHttpInterceptor'; 5 | 6 | // TODO: replace app with your module name 7 | angular.module('app.security') 8 | .factory(id, ['appSettingsService', clientIdHttpInterceptor]); 9 | 10 | function clientIdHttpInterceptor(appSettingsService) { 11 | var interceptor = { 12 | request: request 13 | }; 14 | 15 | return interceptor; 16 | 17 | function request(config) { 18 | var clientId = appSettingsService.clientId; 19 | 20 | if (clientId) { 21 | config.headers['client_authorization'] = clientId; 22 | } 23 | 24 | return config; 25 | } 26 | } 27 | })(); -------------------------------------------------------------------------------- /Secured/spa/security/externalRegister.html: -------------------------------------------------------------------------------- 1 | 
2 |
3 |

{{::vm.title}}

4 |
5 |

Associate your {{::vm.externlProvider}} account.

6 |
7 |
8 | 9 | 10 | 11 | checking email... 12 | a user already exists with this email 13 | 14 | required 15 | email is not valid 16 | 17 |
18 |
19 | 20 | 21 | 22 | checking username... 23 | username already taken 24 | 25 |
26 |
27 | 28 |
29 |
30 |
31 |
32 | -------------------------------------------------------------------------------- /Secured/spa/security/externalSignIn.html: -------------------------------------------------------------------------------- 1 | 
2 |

{{::vm.title}}

3 |
    4 |
  • 5 | 6 |
  • 7 |
8 |
9 | -------------------------------------------------------------------------------- /Secured/spa/security/manage.html: -------------------------------------------------------------------------------- 1 | 
2 |
3 |

{{::vm.title}}

4 |
5 |
6 | 7 | 8 |
9 |
10 |
    11 |
  • Registered logins

  • 12 |
  • 13 | 14 |
  • 15 |
16 |
    17 |
  • Add another login

  • 18 |
  • 19 | 20 |
  • 21 |
22 |
23 |
24 |
25 |
-------------------------------------------------------------------------------- /Secured/spa/security/restoreUserService.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | var serviceId = 'restoreUserService'; 5 | 6 | // TODO: replace app with your module name 7 | angular.module('app.security') 8 | .factory(serviceId, ['$location','$q', 'storageService', 'appActivityService', 'userService', restoreUserService]); 9 | 10 | function restoreUserService($location, $q, storageService, appActivityService, userService) { 11 | 12 | var service = { 13 | restore: restore 14 | }; 15 | 16 | return service; 17 | 18 | function restore() { 19 | appActivityService.busy("restoreUserService"); 20 | 21 | if (storageService.retrieve("accessToken")) { 22 | return userService.getUserInfo().then( 23 | function (result) { 24 | if (result.hasRegistered) { 25 | userService.setUser(result); 26 | appActivityService.idle("restoreUserService"); 27 | } else { 28 | appActivityService.idle("restoreUserService"); 29 | $location.path("/signIn"); 30 | } 31 | }, 32 | function (result) { 33 | //error 34 | appActivityService.idle("restoreUserService"); 35 | $location.path("/signIn"); 36 | }); 37 | } else { 38 | return $q(function (resolve, reject) { 39 | appActivityService.idle("restoreUserService"); 40 | resolve(false); 41 | }); 42 | } 43 | 44 | } 45 | } 46 | })(); -------------------------------------------------------------------------------- /Secured/spa/security/secureHttpInterceptor.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | var id = 'secureHttpInterceptor'; 5 | 6 | // TODO: replace app with your module name 7 | angular.module('app.security') 8 | .factory(id, ['storageService', secureHttpInterceptor]); 9 | 10 | function secureHttpInterceptor(storageService) { 11 | var interceptor = { 12 | request: request 13 | }; 14 | 15 | return interceptor; 16 | 17 | function request(config) { 18 | var token = storageService.retrieve("accessToken"); 19 | 20 | if (token) { 21 | config.headers['Authorization'] = "Bearer " + token; 22 | } 23 | 24 | return config; 25 | } 26 | } 27 | })(); -------------------------------------------------------------------------------- /Secured/spa/security/signIn.html: -------------------------------------------------------------------------------- 1 | 
2 |
3 |

{{::vm.title}}

4 |
5 |
6 | 7 | 8 | 9 | required 10 | 11 |
12 |
13 | 14 | 15 | 16 | required 17 | 18 |
19 |
20 | 23 |
24 | 25 |
26 |
27 |
    28 |
  • Forgotten your password? Click here
  • 29 |
  • New here? sign up here
  • 30 |
31 |
32 |
33 |
-------------------------------------------------------------------------------- /Secured/spa/security/skChangePassword.html: -------------------------------------------------------------------------------- 1 | 
2 |

Change password

3 |
4 |
5 |
6 | 7 | 8 | 9 | required 10 | 11 |
12 |
13 | 14 | 15 | 16 | required 17 | 18 |
19 |
20 | 21 | 22 | 23 | required 24 | passwords do not match 25 | 26 |
27 | 28 |
29 |
-------------------------------------------------------------------------------- /Secured/spa/security/skChangePassword.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | // TODO: replace app with your module name 5 | angular.module('app.security') 6 | .directive('skChangePassword', ['userManagementService', 'baseUrl', skChangePassword]); 7 | 8 | function skChangePassword(userManagementService, baseUrl) { 9 | 10 | var directive = { 11 | link: link, 12 | restrict: 'E', 13 | replace: true, 14 | templateUrl: baseUrl + 'security/skChangePassword.html' 15 | }; 16 | 17 | return directive; 18 | 19 | function link(scope, element, attrs) { 20 | scope.password = ""; 21 | scope.newPassword = ""; 22 | scope.newPasswordConfirm = ""; 23 | scope.change = function () { 24 | var data = { 25 | oldPassword: scope.password, 26 | newPassword: scope.newPassword, 27 | confirmPassword: scope.newPasswordConfirm 28 | }; 29 | 30 | userManagementService.changePassword(data) 31 | .then( 32 | null, 33 | function (result) { 34 | reset(); 35 | }) 36 | .finally( 37 | function () { 38 | reset(); 39 | }); 40 | }; 41 | 42 | function reset() { 43 | scope.password = ""; 44 | scope.newPassword = ""; 45 | scope.newPasswordConfirm = ""; 46 | scope.passwordForm.$setPristine(); 47 | scope.passwordForm.$setUntouched(); 48 | } 49 | 50 | } 51 | } 52 | 53 | })(); -------------------------------------------------------------------------------- /Secured/spa/security/skCreateLocalLogin.html: -------------------------------------------------------------------------------- 1 | 
2 |

Create a local login

3 |
4 |
5 |
6 | 7 | 8 | 9 | required 10 | 11 |
12 |
13 | 14 | 15 | 16 | required 17 | passwords do not match 18 | 19 |
20 | 21 |
22 |
23 | -------------------------------------------------------------------------------- /Secured/spa/security/skCreateLocalLogin.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | // TODO: replace app with your module name 5 | angular.module('app.security') 6 | .directive('skCreateLocalLogin', ['userManagementService', 'baseUrl', skCreateLocalLogin]); 7 | 8 | function skCreateLocalLogin(userManagementService, baseUrl) { 9 | 10 | var directive = { 11 | restrict: 'E', 12 | replace: true, 13 | controller: ['$scope', 'userManagementService', controller], 14 | templateUrl: baseUrl + 'security/skCreateLocalLogin.html' 15 | }; 16 | 17 | return directive; 18 | 19 | function controller($scope, userManagementService) { 20 | $scope.newPassword = ""; 21 | $scope.newPasswordConfirm = ""; 22 | 23 | $scope.create = function () { 24 | var data = { 25 | newPassword: $scope.newPassword, 26 | confirmPassword: $scope.newPasswordConfirm 27 | }; 28 | 29 | userManagementService.addLocalLogin(data) 30 | .finally(function () { 31 | $scope.newPassword = ""; 32 | $scope.newPasswordConfirm = ""; 33 | }); 34 | }; 35 | }; 36 | } 37 | 38 | })(); -------------------------------------------------------------------------------- /Secured/spa/security/skLoginProvider.html: -------------------------------------------------------------------------------- 1 | 
2 |
{{provider.name}}
3 |
4 |
-------------------------------------------------------------------------------- /Secured/spa/security/skLoginProvider.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | // TODO: replace app with your module name 5 | angular.module('app.security') 6 | .directive('skLoginProvider', ['baseUrl', skLoginProvider]); 7 | 8 | function skLoginProvider(baseUrl) { 9 | var directive = { 10 | restrict: 'AE', 11 | replace: true, 12 | scope: { 13 | provider: '=', 14 | action: '&' 15 | }, 16 | templateUrl: baseUrl + 'security/skLoginProvider.html' 17 | }; 18 | 19 | return directive; 20 | } 21 | 22 | })(); -------------------------------------------------------------------------------- /Secured/spa/security/skRequiredRoles.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | // TODO: replace app with your module name 5 | angular.module('app.security') 6 | .directive('skRequiredRoles', skRequiredRoles); 7 | 8 | skRequiredRoles.$inject = ['guardSvc']; 9 | 10 | function skRequiredRoles(guardSvc) { 11 | var directive = { 12 | restrict: 'A', 13 | link: link 14 | }; 15 | 16 | return directive; 17 | 18 | function link(scope, element, attr) { 19 | scope.$watch(attr.skRequiredRoles, function (value) { 20 | 21 | }); 22 | } 23 | } 24 | 25 | })(); -------------------------------------------------------------------------------- /Secured/spa/security/skUserInfo.html: -------------------------------------------------------------------------------- 1 | 
2 | {{username}} 3 | 4 | sign in 5 |
-------------------------------------------------------------------------------- /Secured/spa/security/skUserInfo.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | // TODO: replace app with your module name 5 | angular.module('app.security') 6 | .directive('skUserInfo', ['$rootScope','$location','userService','appStatusService', 'guardService', 'baseUrl', skUserInfo]); 7 | 8 | function skUserInfo($rootScope, $location, userService, appStatusService, guardService, baseUrl) { 9 | var directive = { 10 | restrict: 'E', 11 | replace: true, 12 | templateUrl: baseUrl + 'security/skUserInfo.html', 13 | link: link 14 | 15 | }; 16 | 17 | //TODO: evaluate whether it is best just to watch the sigedIn and user properties 18 | function link($scope, $element, attrs, ctrl) { 19 | $scope.username = userService.info.username; 20 | $scope.signedIn = userService.info.signedIn; 21 | 22 | $scope.signOut = function () { 23 | userService.signOut(); 24 | $location.path('/'); 25 | }; 26 | 27 | $scope.signIn = function () { 28 | guardService.redirectToSignIn(); 29 | }; 30 | 31 | 32 | $rootScope.$on("userService:signedInChanged", function (event, args) { 33 | $scope.signedIn = userService.info.signedIn; 34 | $scope.username = userService.info.username; 35 | }); 36 | } 37 | 38 | return directive; 39 | } 40 | 41 | })(); -------------------------------------------------------------------------------- /Secured/spa/security/skUserLogin.html: -------------------------------------------------------------------------------- 1 | 
2 |
{{login.loginProvider}}
3 |
4 |
5 | -------------------------------------------------------------------------------- /Secured/spa/security/skUserLogin.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | // TODO: replace app with your module name 5 | angular.module('app.security') 6 | .directive('skUserLogin', ['baseUrl', skUserLogin]); 7 | 8 | function skUserLogin(baseUrl) { 9 | var directive = { 10 | restrict: 'AE', 11 | replace: true, 12 | scope: { 13 | login: '=', 14 | action: '&' 15 | }, 16 | templateUrl: baseUrl + 'security/skUserLogin.html' 17 | }; 18 | 19 | return directive; 20 | } 21 | 22 | })(); -------------------------------------------------------------------------------- /Secured/spa/security/usedLoginProviderFilter.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | angular.module('app.security') 5 | .filter('usedLoginProviderFilter',['utilityService', function(utilityService) { 6 | return function (loginProviders, userLogins) { 7 | var filtered = []; 8 | 9 | loginProviders.forEach(function (lp) { 10 | if (utilityService.arrayContains(userLogins, function (ul) { return lp.name === ul.loginProvider; }) !== true) { 11 | filtered.push(lp); 12 | } 13 | }); 14 | 15 | return filtered; 16 | } 17 | }]); 18 | })(); 19 | -------------------------------------------------------------------------------- /Secured/spa/shell/ShellController.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | angular.module('app.shell') 5 | .controller('ShellController', ShellController); 6 | 7 | function ShellController() { 8 | /* jshint validthis:true */ 9 | var vm = this; 10 | } 11 | 12 | })(); 13 | -------------------------------------------------------------------------------- /Secured/spa/shell/shell.html: -------------------------------------------------------------------------------- 1 | 
2 | 3 |
4 |
5 |
6 |
7 |
8 |

loading...

9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | AngularJs starter kit 27 |
28 | 31 |
32 |
33 |
34 |
35 |
-------------------------------------------------------------------------------- /Secured/spa/shell/shell.module.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | var shell = angular.module('app.shell', []); 5 | 6 | //shell.config(['$routeProvider', function ($routeProvider) { 7 | //}]); 8 | 9 | })(); -------------------------------------------------------------------------------- /Secured/spa/shell/skBusyIndicator.html: -------------------------------------------------------------------------------- 1 | 
2 |
3 |
4 | -------------------------------------------------------------------------------- /Secured/spa/shell/skBusyIndicator.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | // TODO: replace app with your module name 5 | angular.module('app.shell') 6 | .directive('skBusyIndicator', ['baseUrl', skBusyIndicator]); 7 | 8 | function skBusyIndicator(baseUrl) { 9 | var directive = { 10 | controller: ['$rootScope', '$scope', controller], 11 | restrict: 'E', 12 | replace: true, 13 | templateUrl: baseUrl + 'shell/skBusyIndicator.html' 14 | 15 | }; 16 | 17 | return directive; 18 | 19 | function controller($rootScope, $scope) { 20 | $scope.isBusy = false; 21 | 22 | $rootScope.$on("appActivityService:isBusyChanged", function (event, args) { 23 | $scope.isBusy = args.busy; 24 | }); 25 | } 26 | } 27 | 28 | })(); -------------------------------------------------------------------------------- /Secured/spa/shell/skLoadingScreen.html: -------------------------------------------------------------------------------- 1 | 
2 |
3 |
4 |

{{::title}}

5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | -------------------------------------------------------------------------------- /Secured/spa/shell/skLoadingScreen.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('app.shell') 6 | .directive('skLoadingScreen', skLoadingScreen); 7 | 8 | skLoadingScreen.$inject = ['baseUrl', 'appStatusService', 'appSettingsService']; 9 | 10 | function skLoadingScreen(baseUrl, appStatusService, appSettingsService) { 11 | var directive = { 12 | link: link, 13 | restrict: 'E', 14 | templateUrl: baseUrl + 'shell/skLoadingScreen.html' 15 | }; 16 | return directive; 17 | 18 | function link(scope, element, attrs) { 19 | scope.title = appSettingsService.title; 20 | scope.hide = false; 21 | 22 | scope.$watch(function () { 23 | return appStatusService.info.loading; 24 | }, function (value) { 25 | scope.hide = !value; 26 | }); 27 | 28 | } 29 | } 30 | 31 | })(); -------------------------------------------------------------------------------- /Secured/spa/shell/skNavLink.html: -------------------------------------------------------------------------------- 1 | 
  • 2 | 3 | 4 | 7 |
  • -------------------------------------------------------------------------------- /Secured/spa/shell/skNavLink.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | angular 5 | .module('app.shell') 6 | .directive('skNavLink', skNavLink); 7 | 8 | skNavLink.$inject = ['$filter', '$templateRequest', '$compile', '$rootScope', 'baseUrl']; 9 | 10 | function skNavLink($filter, $templateRequest, $compile, $rootScope, baseUrl) { 11 | var directive = { 12 | restrict: 'E', 13 | scope: { 14 | navLink: '=' 15 | }, 16 | replace: true, 17 | link: link 18 | }; 19 | return directive; 20 | 21 | function link(scope, element, attrs) { 22 | $templateRequest(baseUrl + 'shell/skNavLink.html').then(function (result) { 23 | scope.navLinks = scope.$parent.navLinks || scope.$parent.$parent.navLinks; 24 | scope.hasChildren = $filter('filter')(scope.navLinks, { 25 | parent: scope.navLink.name 26 | }).length > 0; 27 | 28 | var template = angular.element(result); 29 | 30 | if (!scope.hasChildren) { 31 | template.children(".child-nav-links").remove(); 32 | } 33 | 34 | var el = $compile(template)(scope); 35 | element.replaceWith(el); 36 | }); 37 | 38 | $rootScope.$on('$routeChangeSuccess', function (event, next, current) { 39 | if (!scope.navLink.parent && next.$$route) { 40 | scope.navLink.isActive = scope.navLink.name === next.$$route.showNav 41 | || scope.navLink.name === next.$$route.parent; 42 | } 43 | }); 44 | } 45 | } 46 | })(); -------------------------------------------------------------------------------- /Secured/spa/shell/skNavLinks.html: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /Secured/spa/shell/skNavLinks.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | angular 5 | .module('app.shell') 6 | .directive('skNavLinks', skNavLinks); 7 | 8 | skNavLinks.$inject = ['$rootScope', '$location', 'baseUrl']; 9 | 10 | function skNavLinks($rootScope, $location, baseUrl) { 11 | var directive = { 12 | link: link, 13 | restrict: 'E', 14 | scope: { 15 | navLinks: '=' 16 | }, 17 | replace: true, 18 | templateUrl: baseUrl + 'shell/skNavLinks.html' 19 | }; 20 | return directive; 21 | 22 | function link(scope, element, attrs) { 23 | scope.isTopLevel = function (link) { 24 | return !link.parent; 25 | }; 26 | 27 | setInitialActive(); 28 | 29 | function setInitialActive() { 30 | if (scope.navLinks && $location.path()) { 31 | var activePath = $location.path().substring(1); 32 | scope.navLinks.forEach(function (navLink) { 33 | navLink.isActive = navLink.url === activePath; 34 | }); 35 | } 36 | } 37 | } 38 | } 39 | })(); -------------------------------------------------------------------------------- /Secured/spa/shell/skTopNav.html: -------------------------------------------------------------------------------- 1 | 
    2 | 25 |
    -------------------------------------------------------------------------------- /Secured/spa/shell/skTopNav.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('app.shell') 6 | .directive('skTopNav', skTopNav); 7 | 8 | skTopNav.$inject = ['appSettingsService', 'navigationService', 'baseUrl']; 9 | 10 | function skTopNav(appSettingsService, navigationService, baseUrl) { 11 | var directive = { 12 | link: link, 13 | restrict: 'E', 14 | replace: true, 15 | templateUrl: baseUrl + 'shell/skTopNav.html' 16 | }; 17 | return directive; 18 | 19 | function link(scope, element, attrs) { 20 | scope.title = appSettingsService.title; 21 | scope.brand = appSettingsService.brand; 22 | scope.links = navigationService.getLinks(); 23 | } 24 | } 25 | 26 | })(); -------------------------------------------------------------------------------- /Spa/App_Start/SpaRouteConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using System.Web.Routing; 7 | 8 | [assembly: WebActivatorEx.PreApplicationStartMethod(typeof(Spa.App_Start.SpaRouteConfig), "RegisterRoutes")] 9 | namespace Spa.App_Start 10 | { 11 | 12 | public class SpaRouteConfig 13 | { 14 | public static void RegisterRoutes() 15 | { 16 | var routes = RouteTable.Routes; 17 | 18 | //will stop mvc trying to route to thr physical app folder 19 | routes.RouteExistingFiles = true; 20 | 21 | routes.MapRoute( 22 | name: "Spa", 23 | url: "spa/{*all}", 24 | defaults: new { controller = "spa", action = "Index", id = UrlParameter.Optional }); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Spa/Content/fadeAnimation.css: -------------------------------------------------------------------------------- 1 | .fade-animation.ng-leave{-moz-transition:.2s ease-in all;-o-transition:.2s ease-in all;-webkit-transition:.2s ease-in all;transition:.2s ease-in all;opacity:1}.fade-animation.ng-leave.ng-leave-active{opacity:0}.fade-animation.ng-enter{-moz-transition:.2s ease-in all .2s;-o-transition:.2s ease-in all .2s;-webkit-transition:.2s ease-in all .2s;transition:.2s ease-in all .2s;opacity:0}.fade-animation.ng-enter.ng-enter-active{opacity:1} -------------------------------------------------------------------------------- /Spa/Content/spa.css: -------------------------------------------------------------------------------- 1 | #sk-busy-indicator{height:20px;width:20px;padding:0}.spinner-small{-webkit-animation:rotation .6s infinite linear;-moz-animation:rotation .6s infinite linear;-o-animation:rotation .6s infinite linear;animation:rotation .6s infinite linear;border-left:3px solid rgba(0,0,0,.15);border-right:3px solid rgba(0,0,0,.15);border-bottom:3px solid rgba(0,0,0,.15);border-top:3px solid rgba(0,0,0,.8)}.spinner-large-container{margin-top:50px;margin-bottom:50px}.spinner-large{-webkit-animation:rotation 1.5s infinite linear;-moz-animation:rotation 1.5s infinite linear;-o-animation:rotation 1.5s infinite linear;animation:rotation 1.5s infinite linear;border-left:6px solid gray;border-right:6px solid gray;border-bottom:6px solid gray;border-top:6px solid #fff;height:50px;width:50px}.spinner{height:100%;width:100%;margin:0 auto;position:relative;border-radius:100%}@-webkit-keyframes rotation{from{-webkit-transform:rotate(0deg)}to{-webkit-transform:rotate(359deg)}}@-moz-keyframes rotation{from{-moz-transform:rotate(0deg)}to{-moz-transform:rotate(359deg)}}@-o-keyframes rotation{from{-o-transform:rotate(0deg);}to{-o-transform:rotate(359deg);}}@keyframes rotation{from{transform:rotate(0deg)}to{transform:rotate(359deg)}} -------------------------------------------------------------------------------- /Spa/Controllers/SpaController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | 7 | namespace Spa.Controllers 8 | { 9 | public class SpaController : Controller 10 | { 11 | public ActionResult Index() 12 | { 13 | return View(); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Spa/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JayChase/Angular.Net.SecureStarter/f4ef56b342be9c1aee55990e0b4431e0cc8c8626/Spa/Icon.png -------------------------------------------------------------------------------- /Spa/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Spa")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Spa")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("b8e9192c-df24-4a1d-9875-7b9431378ad0")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /Spa/Scripts/angular-cookies.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | AngularJS v1.3.15 3 | (c) 2010-2014 Google, Inc. http://angularjs.org 4 | License: MIT 5 | */ 6 | (function(p,f,n){'use strict';f.module("ngCookies",["ng"]).factory("$cookies",["$rootScope","$browser",function(e,b){var c={},g={},h,k=!1,l=f.copy,m=f.isUndefined;b.addPollFn(function(){var a=b.cookies();h!=a&&(h=a,l(a,g),l(a,c),k&&e.$apply())})();k=!0;e.$watch(function(){var a,d,e;for(a in g)m(c[a])&&b.cookies(a,n);for(a in c)d=c[a],f.isString(d)||(d=""+d,c[a]=d),d!==g[a]&&(b.cookies(a,d),e=!0);if(e)for(a in d=b.cookies(),c)c[a]!==d[a]&&(m(d[a])?delete c[a]:c[a]=d[a])});return c}]).factory("$cookieStore", 7 | ["$cookies",function(e){return{get:function(b){return(b=e[b])?f.fromJson(b):b},put:function(b,c){e[b]=f.toJson(c)},remove:function(b){delete e[b]}}}])})(window,window.angular); 8 | //# sourceMappingURL=angular-cookies.min.js.map 9 | -------------------------------------------------------------------------------- /Spa/Scripts/angular-cookies.min.js.map: -------------------------------------------------------------------------------- 1 | { 2 | "version":3, 3 | "file":"angular-cookies.min.js", 4 | "lineCount":7, 5 | "mappings":"A;;;;;aAKC,SAAQ,CAACA,CAAD,CAASC,CAAT,CAAkBC,CAAlB,CAA6B,CAmBtCD,CAAAE,OAAA,CAAe,WAAf,CAA4B,CAAC,IAAD,CAA5B,CAAAC,QAAA,CA0BW,UA1BX,CA0BuB,CAAC,YAAD,CAAe,UAAf,CAA2B,QAAQ,CAACC,CAAD,CAAaC,CAAb,CAAuB,CAAA,IACvEC,EAAU,EAD6D,CAEvEC,EAAc,EAFyD,CAGvEC,CAHuE,CAIvEC,EAAU,CAAA,CAJ6D,CAKvEC,EAAOV,CAAAU,KALgE,CAMvEC,EAAcX,CAAAW,YAGlBN,EAAAO,UAAA,CAAmB,QAAQ,EAAG,CAC5B,IAAIC,EAAiBR,CAAAC,QAAA,EACjBE,EAAJ,EAA0BK,CAA1B,GACEL,CAGA,CAHqBK,CAGrB,CAFAH,CAAA,CAAKG,CAAL,CAAqBN,CAArB,CAEA,CADAG,CAAA,CAAKG,CAAL,CAAqBP,CAArB,CACA,CAAIG,CAAJ,EAAaL,CAAAU,OAAA,EAJf,CAF4B,CAA9B,CAAA,EAUAL,EAAA,CAAU,CAAA,CAKVL,EAAAW,OAAA,CASAC,QAAa,EAAG,CAAA,IACVC,CADU,CAEVC,CAFU,CAIVC,CAGJ,KAAKF,CAAL,GAAaV,EAAb,CACMI,CAAA,CAAYL,CAAA,CAAQW,CAAR,CAAZ,CAAJ,EACEZ,CAAAC,QAAA,CAAiBW,CAAjB,CAAuBhB,CAAvB,CAKJ,KAAKgB,CAAL,GAAaX,EAAb,CACEY,CAKA,CALQZ,CAAA,CAAQW,CAAR,CAKR,CAJKjB,CAAAoB,SAAA,CAAiBF,CAAjB,CAIL,GAHEA,CACA,CADQ,EACR,CADaA,CACb,CAAAZ,CAAA,CAAQW,CAAR,CAAA,CAAgBC,CAElB,EAAIA,CAAJ,GAAcX,CAAA,CAAYU,CAAZ,CAAd,GACEZ,CAAAC,QAAA,CAAiBW,CAAjB,CAAuBC,CAAvB,CACA,CAAAC,CAAA,CAAU,CAAA,CAFZ,CAOF,IAAIA,CAAJ,CAIE,IAAKF,CAAL,GAFAI,EAEaf,CAFID,CAAAC,QAAA,EAEJA,CAAAA,CAAb,CACMA,CAAA,CAAQW,CAAR,CAAJ,GAAsBI,CAAA,CAAeJ,CAAf,CAAtB,GAEMN,CAAA,CAAYU,CAAA,CAAeJ,CAAf,CAAZ,CAAJ,CACE,OAAOX,CAAA,CAAQW,CAAR,CADT,CAGEX,CAAA,CAAQW,CAAR,CAHF,CAGkBI,CAAA,CAAeJ,CAAf,CALpB,CAhCU,CAThB,CAEA,OAAOX,EA1BoE,CAA1D,CA1BvB,CAAAH,QAAA,CAoIW,cApIX;AAoI2B,CAAC,UAAD,CAAa,QAAQ,CAACmB,CAAD,CAAW,CAErD,MAAO,CAWLC,IAAKA,QAAQ,CAACC,CAAD,CAAM,CAEjB,MAAO,CADHN,CACG,CADKI,CAAA,CAASE,CAAT,CACL,EAAQxB,CAAAyB,SAAA,CAAiBP,CAAjB,CAAR,CAAkCA,CAFxB,CAXd,CA0BLQ,IAAKA,QAAQ,CAACF,CAAD,CAAMN,CAAN,CAAa,CACxBI,CAAA,CAASE,CAAT,CAAA,CAAgBxB,CAAA2B,OAAA,CAAeT,CAAf,CADQ,CA1BrB,CAuCLU,OAAQA,QAAQ,CAACJ,CAAD,CAAM,CACpB,OAAOF,CAAA,CAASE,CAAT,CADa,CAvCjB,CAF8C,CAAhC,CApI3B,CAnBsC,CAArC,CAAD,CAwMGzB,MAxMH,CAwMWA,MAAAC,QAxMX;", 6 | "sources":["angular-cookies.js"], 7 | "names":["window","angular","undefined","module","factory","$rootScope","$browser","cookies","lastCookies","lastBrowserCookies","runEval","copy","isUndefined","addPollFn","currentCookies","$apply","$watch","push","name","value","updated","isString","browserCookies","$cookies","get","key","fromJson","put","toJson","remove"] 8 | } 9 | -------------------------------------------------------------------------------- /Spa/Scripts/angular-csp.css: -------------------------------------------------------------------------------- 1 | /* Include this file in your html if you are using the CSP mode. */ 2 | 3 | @charset "UTF-8"; 4 | 5 | [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], 6 | .ng-cloak, .x-ng-cloak, 7 | .ng-hide:not(.ng-hide-animate) { 8 | display: none !important; 9 | } 10 | 11 | ng\:form { 12 | display: block; 13 | } 14 | -------------------------------------------------------------------------------- /Spa/Scripts/angular-loader.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | AngularJS v1.3.15 3 | (c) 2010-2014 Google, Inc. http://angularjs.org 4 | License: MIT 5 | */ 6 | (function(){'use strict';function d(b){return function(){var c=arguments[0],e;e="["+(b?b+":":"")+c+"] http://errors.angularjs.org/1.3.15/"+(b?b+"/":"")+c;for(c=1;c").html(a);f.forEach(a.children(), 8 | function(a){a=f.element(a);h?h.after(a):d.prepend(a);h=a;q(a)(b)});c.renderMessages(e,g)})}}}]).directive("ngMessage",["$animate",function(f){return{require:"^ngMessages",transclude:"element",terminal:!0,restrict:"AE",link:function(k,l,b,d,a){for(var c,g,e=l[0],n=e.parentNode,h=0,p=0;h 5 | 6 | 7 | 14 | Angular starter kit 15 | 16 | 17 | 18 | 19 | 28 | 29 | @Styles.Render("~/Content/spaCss") 30 | @Scripts.Render("~/bundles/spaModernizr") 31 | 32 | 33 |
    34 |
    35 | @Scripts.Render("~/bundles/spaVendor") 36 | @Scripts.Render("~/bundles/angular") 37 | @Scripts.Render("~/bundles/common") 38 | @Scripts.Render("~/bundles/content") 39 | @Scripts.Render("~/bundles/shell") 40 | @Scripts.Render("~/bundles/spa") 41 | 42 | 43 | -------------------------------------------------------------------------------- /Spa/Views/web.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
    7 |
    8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /Spa/Web.Debug.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | -------------------------------------------------------------------------------- /Spa/Web.Release.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | -------------------------------------------------------------------------------- /Spa/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /Spa/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JayChase/Angular.Net.SecureStarter/f4ef56b342be9c1aee55990e0b4431e0cc8c8626/Spa/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /Spa/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JayChase/Angular.Net.SecureStarter/f4ef56b342be9c1aee55990e0b4431e0cc8c8626/Spa/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /Spa/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JayChase/Angular.Net.SecureStarter/f4ef56b342be9c1aee55990e0b4431e0cc8c8626/Spa/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /Spa/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JayChase/Angular.Net.SecureStarter/f4ef56b342be9c1aee55990e0b4431e0cc8c8626/Spa/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /Spa/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Spa/spa/app.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | var app = angular.module('app', ['ngRoute', 'ngAnimate', 'app.core', 'app.shell', 'app.content']); 5 | 6 | app.config(['$locationProvider', function ($locationProvider) { 7 | $locationProvider.html5Mode(true); 8 | }]); 9 | 10 | app.run(['$route', function ($route) { 11 | }]); 12 | })(); -------------------------------------------------------------------------------- /Spa/spa/common/common.module.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | var common = angular.module('app.common', []); 5 | })(); -------------------------------------------------------------------------------- /Spa/spa/common/validation/skAsyncValidators.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | angular 5 | .module('app.common') 6 | .directive('skAsyncValidators', skAsyncValidators); 7 | 8 | skAsyncValidators.$inject = ['$parse']; 9 | 10 | function skAsyncValidators($parse) { 11 | var directive = { 12 | require: 'ngModel', 13 | link: link, 14 | restrict: 'A' 15 | }; 16 | 17 | return directive; 18 | 19 | function link(scope, element, attrs, ngModel) { 20 | var asyncValidators = scope.$eval(attrs["skAsyncValidators"]); 21 | 22 | if (asyncValidators) { 23 | angular.extend(ngModel.$asyncValidators, asyncValidators); 24 | } 25 | } 26 | } 27 | })(); -------------------------------------------------------------------------------- /Spa/spa/common/validation/skHasError.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('app.common') 6 | .directive('skHasError', skHasError); 7 | 8 | function skHasError() { 9 | var directive = { 10 | restrict: 'A', 11 | require: 'ngMessages', 12 | link: link 13 | }; 14 | 15 | return directive; 16 | 17 | function link(scope, element, attrs, ngMessages) { 18 | var renderMessages = ngMessages.renderMessages, 19 | hasErrorTarget; 20 | 21 | if (!hasErrorTarget) { 22 | if (attrs.skHasError) { 23 | hasErrorTarget = element.parents('#' + attrs.skHasError); 24 | } else { 25 | hasErrorTarget = element.parent('.form-group'); 26 | } 27 | } 28 | 29 | ngMessages.renderMessages = function (values, multiple, element) { 30 | renderMessages.apply(this, arguments); 31 | 32 | if ($.isEmptyObject(values)) { 33 | hasErrorTarget.removeClass('has-error'); 34 | } else { 35 | hasErrorTarget.addClass('has-error'); 36 | } 37 | }; 38 | } 39 | } 40 | })(); -------------------------------------------------------------------------------- /Spa/spa/common/validation/skMatch.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | angular.module('app.common') 5 | .directive('skMatch', [skMatch]); 6 | 7 | function skMatch() { 8 | var directive = { 9 | restrict: 'A', 10 | require: 'ngModel', 11 | link: link 12 | }; 13 | 14 | return directive; 15 | 16 | function link(scope, element, attrs, ctrl) { 17 | scope.$watchGroup([ 18 | attrs.ngModel, 19 | attrs.skMatch 20 | ], function (newValues) { 21 | ctrl.$setValidity('match', newValues[0] === newValues[1]); 22 | }); 23 | } 24 | } 25 | })(); -------------------------------------------------------------------------------- /Spa/spa/common/validation/skUnique.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | angular 5 | .module('app.common') 6 | .directive('skUnique', skUnique); 7 | 8 | skUnique.$inject = []; 9 | 10 | function skUnique() { 11 | var directive = { 12 | require: 'ngModel', 13 | link: link, 14 | restrict: 'A', 15 | scope: { 16 | skUnique: '&' 17 | } 18 | }; 19 | 20 | return directive; 21 | 22 | function link(scope, element, attrs, ngModel) { 23 | var wrappedValidator = function (mv, vv) { 24 | ngModel.$setValidity('checking', false); 25 | 26 | return scope.skUnique({ value: mv || vv }) 27 | .finally(function () { 28 | ngModel.$setValidity('checking', true); 29 | }); 30 | }; 31 | 32 | ngModel.$asyncValidators.unique = wrappedValidator; 33 | } 34 | } 35 | })(); -------------------------------------------------------------------------------- /Spa/spa/content/content.module.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | var content = angular.module('app.content', []); 5 | 6 | content.config(['$routeProvider', 'baseUrl', function ($routeProvider, baseUrl) { 7 | $routeProvider.when('/', { 8 | templateUrl: baseUrl + 'content/welcome/welcome.html', 9 | controller: 'WelcomeController', 10 | controllerAs: 'vm', 11 | caseInsensitiveMatch: true 12 | }) 13 | .when('/welcome', { 14 | templateUrl: baseUrl + 'content/welcome/welcome.html', 15 | controller: 'WelcomeController', 16 | controllerAs: 'vm', 17 | caseInsensitiveMatch: true, 18 | showNav: 'welcome' 19 | }) 20 | .when('/features', { 21 | templateUrl: baseUrl +'content/features/features.html', 22 | controller: 'FeaturesController', 23 | controllerAs: 'vm', 24 | caseInsensitiveMatch: true, 25 | showNav: 'features' 26 | }) 27 | .otherwise('/'); 28 | }]); 29 | 30 | })(); -------------------------------------------------------------------------------- /Spa/spa/content/features/FeaturesController.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | angular.module('app.content') 5 | .controller('FeaturesController', FeaturesController); 6 | 7 | FeaturesController.$inject = ['notifierService', 'appActivityService']; 8 | 9 | function FeaturesController(notifierService, appActivityService) { 10 | /* jshint validthis:true */ 11 | var vm = this; 12 | 13 | vm.title = 'features'; 14 | vm.features = []; 15 | 16 | activate(); 17 | 18 | function activate() { 19 | var busy = false, notifierFeature, appActivityFeature, navigationFeature, authorizationFeature; 20 | 21 | notifierFeature = { 22 | name: "notifier service (notifierService)", 23 | description: "Wraps toastr to make creating user info popups from anywhere in your app easy. Click the demo button to send a message.", 24 | demo: function () { 25 | notifierService.show({message: "A message from the notifierService"}); 26 | } 27 | }; 28 | 29 | vm.features.push(notifierFeature); 30 | 31 | appActivityFeature = { 32 | name: "application activity service (appActivityService)", 33 | description: "Allows the app to track whether it is busy or not. Use the busy/idle methods let the app know. Also use the sk-disable-when-busy directive to disable elements whilst the app is busy.", 34 | demo: function () { 35 | if (busy) { 36 | appActivityService.idle("demo"); 37 | busy = false; 38 | } else { 39 | appActivityService.busy("demo"); 40 | busy = true; 41 | } 42 | } 43 | }; 44 | 45 | vm.features.push(appActivityFeature); 46 | 47 | navigationFeature = { 48 | name: "Dynamic navbar links", 49 | description: "Add the property showNav to a route to show it as a link in the navbar. eg showNav: 'linkText'" 50 | }; 51 | 52 | vm.features.push(navigationFeature); 53 | } 54 | } 55 | })(); 56 | -------------------------------------------------------------------------------- /Spa/spa/content/features/features.html: -------------------------------------------------------------------------------- 1 | 
    2 |
    3 |

    {{::vm.title}}

    4 |
      5 |
    • 6 |

      {{f.name}}

      7 |

      {{f.description}}

      8 | 9 |
    • 10 |
    11 |
    12 |
    -------------------------------------------------------------------------------- /Spa/spa/content/welcome/WelcomeController.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | angular.module('app.content') 5 | .controller('WelcomeController',WelcomeController); 6 | 7 | function WelcomeController() { 8 | /* jshint validthis:true */ 9 | var vm = this; 10 | 11 | vm.title = 'Angular starter kit'; 12 | 13 | activate(); 14 | 15 | function activate() { } 16 | } 17 | })(); 18 | -------------------------------------------------------------------------------- /Spa/spa/content/welcome/welcome.html: -------------------------------------------------------------------------------- 1 | 
    2 |
    3 |
    4 |

    {{::vm.title}}

    5 |

    6 | A base project with user authentication/authorization and some other bits to make life a bit easier. See the project wiki for more help getting started. 7 |

    8 |

    9 | wiki 10 |

    11 |
    12 |
    13 |
    14 | 15 | -------------------------------------------------------------------------------- /Spa/spa/core/appActivityService.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | var serviceId = 'appActivityService'; 5 | 6 | angular.module('app.core') 7 | .factory(serviceId, ['$rootScope', appActivityService]); 8 | 9 | function appActivityService($rootScope) { 10 | var service = { 11 | busy: busy, 12 | idle: idle, 13 | info:{ 14 | isBusy: false 15 | }, 16 | reset: reset 17 | }; 18 | 19 | var activities = []; 20 | 21 | return service; 22 | 23 | function busy(name) { 24 | if (!name) { 25 | throw {name:'Error', message:'A valid activity name must be provided.'}; 26 | } 27 | 28 | if (!activities[name]) { 29 | activities.push(name); 30 | } 31 | 32 | updateStatus(); 33 | } 34 | 35 | function idle(name) { 36 | if (!name) { 37 | throw { name: 'Error', message: 'A valid activity name must be provided.' }; 38 | } 39 | 40 | if (!activities[name]) { 41 | activities.pop(name); 42 | } 43 | 44 | updateStatus(); 45 | } 46 | 47 | function updateStatus() { 48 | 49 | var newStatus = activities.length > 0; 50 | 51 | if(service.info.isBusy !== newStatus){ 52 | service.info.isBusy = newStatus; 53 | $rootScope.$broadcast("appActivityService:isBusyChanged", { busy: service.info.isBusy }); 54 | } 55 | } 56 | 57 | function reset() { 58 | activities = []; 59 | updateStatus(); 60 | } 61 | } 62 | })(); -------------------------------------------------------------------------------- /Spa/spa/core/appStatusService.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | var serviceId = 'appStatusService'; 5 | 6 | // TODO: replace app with your module name 7 | angular.module('app.core') 8 | .factory(serviceId, ['$q', appStatusService]); 9 | 10 | function appStatusService($q) { 11 | var deferreds = []; 12 | 13 | var service = { 14 | whenReady: whenReady, 15 | info:{ 16 | ready: false 17 | }, 18 | isReady: isReady 19 | }; 20 | 21 | return service; 22 | 23 | function isReady(value) { 24 | if (service.info.ready !== value) { 25 | service.info.ready = value; 26 | 27 | if (service.info.ready) { 28 | resolvePromises(); 29 | } 30 | } 31 | } 32 | 33 | function whenReady() { 34 | var deferred = $q.defer(); 35 | 36 | if (service.info.ready) { 37 | deferred.resolve(); 38 | } else { 39 | deferreds.push(deferred); 40 | } 41 | 42 | return deferred.promise; 43 | } 44 | 45 | function resolvePromises() { 46 | deferreds.forEach(function (deferred) { 47 | deferred.resolve(); 48 | }); 49 | 50 | deferreds.length = 0; 51 | } 52 | } 53 | })(); -------------------------------------------------------------------------------- /Spa/spa/core/core.module.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | var core = angular.module('app.core', ['app.common']); 4 | 5 | core.config(['$provide', function ($provide) { 6 | $provide.constant("baseUrl", ""); //url to the server location of the spa (requires trailing slash) 7 | $provide.constant("siteUrl", angular.element('base')[0].href); //will have trailing slash 8 | }]); 9 | 10 | //if a client_id header is required add the clientId property to the appSettingsService 11 | core.value('appSettingsService', { 12 | brand: 'AngulerStarterKit', 13 | title: 'Angular Starter Kit' 14 | }); 15 | })(); -------------------------------------------------------------------------------- /Spa/spa/core/navigationService.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | var serviceId = 'navigationService'; 5 | 6 | angular.module('app.core') 7 | .factory(serviceId, ['$route',navigationService]); 8 | 9 | function navigationService($route) { 10 | var links = []; 11 | 12 | var service = { 13 | getLinks: getLinks 14 | }; 15 | 16 | createLinks(); 17 | 18 | function createLinks() { 19 | angular.forEach($route.routes, function (route) { 20 | if (route.showNav) { 21 | links.push({ 22 | name: route.showNav, 23 | url: (removeStartSlash(route.navPath) || removeStartSlash(route.originalPath)), 24 | parent: route.parent 25 | }); 26 | } 27 | }); 28 | } 29 | 30 | function getLinks() { 31 | return links; 32 | } 33 | 34 | return service; 35 | 36 | function removeStartSlash(path) { 37 | if (path && path.charAt(0) === '/') { 38 | path = path.substring(1); 39 | } 40 | 41 | return path; 42 | } 43 | } 44 | })(); -------------------------------------------------------------------------------- /Spa/spa/core/notifierService.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | var serviceId = 'notifierService'; 5 | 6 | toastr.options.closeButton = true; 7 | toastr.options.positionClass = 'toast-bottom-right'; 8 | toastr.options.backgroundpositionClass = 'toast-bottom-right'; 9 | toastr.options.timeOut = 800; 10 | toastr.options.fadeOut = 50; 11 | toastr.options.fadeIn = 50; 12 | 13 | var defaults = { 14 | source: "app", 15 | title: "", 16 | message: "no message provided", 17 | detail: "", 18 | type: "info" 19 | }; 20 | 21 | angular.module('app.core') 22 | .factory(serviceId, [notifierService]); 23 | 24 | function notifierService() { 25 | var service = { 26 | show: show, 27 | verbose: true 28 | }; 29 | 30 | return service; 31 | 32 | function show(options) { 33 | var opns = angular.copy(defaults); 34 | 35 | if (typeof options === "string") { 36 | opns.message = options; 37 | } else { 38 | opns = angular.extend(opns, options); 39 | } 40 | 41 | if (service.verbose && opns.detail.length > 0) { 42 | opns.message += " " + opns.detail; 43 | } 44 | 45 | toastr[opns.type](opns.message, opns.title); 46 | } 47 | } 48 | })(); -------------------------------------------------------------------------------- /Spa/spa/core/skAppReady.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular.module('app.core') 5 | .directive('skAppReady', ['appStatusService', skAppReady]); 6 | 7 | function skAppReady(appStatusService) { 8 | 9 | var directive = { 10 | link: link, 11 | restrict: 'A', 12 | scope: { 13 | 14 | } 15 | }; 16 | return directive; 17 | 18 | function link(scope, element, attr) { 19 | appStatusService.isReady(attr.skAppReady); 20 | } 21 | } 22 | 23 | })(); -------------------------------------------------------------------------------- /Spa/spa/core/skDisableWhenBusy.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular.module('app.core') 5 | .directive('skDisableWhenBusy', ['$rootScope', skDisableWhenBusy]); 6 | 7 | function skDisableWhenBusy($rootScope) { 8 | var directive = { 9 | link: link, 10 | restrict: 'A', 11 | scope: { 12 | disableOn: '=' 13 | } 14 | }; 15 | 16 | return directive; 17 | 18 | function link(scope, element, attrs) { 19 | var target = element, 20 | disable = setDisable(scope.disableOn), 21 | busy = false; 22 | 23 | scope.$watch("disableOn", function (value) { 24 | setDisable(value); 25 | updateDisabled(); 26 | }); 27 | 28 | $rootScope.$on("appActivityService:isBusyChanged", function (event, args) { 29 | busy = args.busy; 30 | updateDisabled(); 31 | }); 32 | 33 | function updateDisabled() { 34 | angular.element(target).prop('disabled', disable || busy); 35 | } 36 | 37 | function setDisable(boolArray) { 38 | var result = false; 39 | 40 | if (boolArray) { 41 | boolArray.forEach(function (b) { 42 | if (b) { 43 | result = true; 44 | } 45 | }); 46 | } 47 | 48 | disable = result; 49 | } 50 | } 51 | } 52 | })(); -------------------------------------------------------------------------------- /Spa/spa/core/skFocusOnSetPristine.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('app.core') 6 | .directive('skFocusOnSetPristine', skFocusOnSetPristine); 7 | 8 | 9 | function skFocusOnSetPristine () { 10 | 11 | var directive = { 12 | link: link, 13 | restrict: 'A' 14 | }; 15 | return directive; 16 | 17 | function link(scope, element, attrs) { 18 | //get the parent form element and form on the scope 19 | var formElement = element.parents('form'), 20 | form = scope[formElement.attr('name')], 21 | focusElement = element; 22 | 23 | scope.$watch(function () { 24 | return form.$pristine; 25 | 26 | }, 27 | function (newValue, oldValue) { 28 | if (newValue && !oldValue) { 29 | element.focus(); 30 | } 31 | }); 32 | } 33 | } 34 | 35 | })(); -------------------------------------------------------------------------------- /Spa/spa/core/storageService.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | var serviceId = 'storageService'; 5 | 6 | angular.module('app.core') 7 | .factory(serviceId, ['utilityService', storageService]); 8 | 9 | function storageService(utilityService) { 10 | var service = { 11 | store: store, 12 | retrieve: retrieve, 13 | remove: remove, 14 | clear: clear, 15 | saveSession: saveSession 16 | }; 17 | 18 | return service; 19 | 20 | //key value json (if true: stringify then store) 21 | function store(key, value, persist) { 22 | if (utilityService.exists(value) && utilityService.isObject(value)) { 23 | value = "!!stringified!!" + JSON.stringify(value); 24 | } 25 | 26 | if (persist) { 27 | localStorage.setItem(key,value); 28 | } else { 29 | sessionStorage.setItem(key, value); 30 | 31 | if (utilityService.exists(localStorage.getItem(key))) { 32 | localStorage.removeItem(key); 33 | } 34 | } 35 | } 36 | 37 | //key value json (if true: parse) 38 | function retrieve(key) { 39 | //if key exists in session storage return that if not try to return local 40 | var value; 41 | 42 | value = localStorage.getItem(key); 43 | 44 | if (!value) { 45 | value = sessionStorage.getItem(key); 46 | } 47 | 48 | if (utilityService.exists(value) && value.indexOf("!!stringified!!") > -1) { 49 | value = value.replace("!!stringified!!", ""); 50 | value = JSON.parse(value); 51 | } 52 | 53 | return value; 54 | } 55 | 56 | function remove(key) { 57 | localStorage.removeItem(key); 58 | sessionStorage.removeItem(key); 59 | } 60 | 61 | //sessionOnly only clear the local (persisted) storage 62 | function clear(sessionOnly) { 63 | if (!sessionOnly) { 64 | localStorage.clear(); 65 | } 66 | 67 | sessionStorage.clear(); 68 | } 69 | 70 | function saveSession() { 71 | angular.extend(localStorage, sessionStorage); 72 | } 73 | } 74 | })(); -------------------------------------------------------------------------------- /Spa/spa/shell/ShellController.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | angular.module('app.shell') 5 | .controller('ShellController', ShellController); 6 | 7 | function ShellController() { 8 | /* jshint validthis:true */ 9 | var vm = this; 10 | } 11 | 12 | })(); 13 | -------------------------------------------------------------------------------- /Spa/spa/shell/shell.html: -------------------------------------------------------------------------------- 1 | 
    2 | 3 |
    4 |
    5 |
    6 |
    7 |
    8 |

    loading...

    9 |
    10 |
    11 |
    12 |
    13 |
    14 |
    15 |
    16 |
    17 |
    18 |
    19 |
    20 |
    21 |
    22 |
    23 |
    24 |
    25 |
    26 | AngularJs starter kit 27 |
    28 | 31 |
    32 |
    33 |
    34 |
    35 |
    -------------------------------------------------------------------------------- /Spa/spa/shell/shell.module.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | var shell = angular.module('app.shell', []); 5 | 6 | //shell.config(['$routeProvider', function ($routeProvider) { 7 | //}]); 8 | 9 | })(); -------------------------------------------------------------------------------- /Spa/spa/shell/skBusyIndicator.html: -------------------------------------------------------------------------------- 1 | 
    2 |
    3 |
    4 | -------------------------------------------------------------------------------- /Spa/spa/shell/skBusyIndicator.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | // TODO: replace app with your module name 5 | angular.module('app.shell') 6 | .directive('skBusyIndicator', ['baseUrl', skBusyIndicator]); 7 | 8 | function skBusyIndicator(baseUrl) { 9 | var directive = { 10 | controller: ['$rootScope', '$scope', controller], 11 | restrict: 'E', 12 | replace: true, 13 | templateUrl: baseUrl + 'shell/skBusyIndicator.html' 14 | 15 | }; 16 | 17 | return directive; 18 | 19 | function controller($rootScope, $scope) { 20 | $scope.isBusy = false; 21 | 22 | $rootScope.$on("appActivityService:isBusyChanged", function (event, args) { 23 | $scope.isBusy = args.busy; 24 | }); 25 | } 26 | } 27 | 28 | })(); -------------------------------------------------------------------------------- /Spa/spa/shell/skLoadingScreen.html: -------------------------------------------------------------------------------- 1 | 
    2 |
    3 |
    4 |

    {{::title}}

    5 |
    6 |
    7 |
    8 |
    9 |
    10 |
    11 |
    12 |
    13 |
    14 |
    15 | -------------------------------------------------------------------------------- /Spa/spa/shell/skLoadingScreen.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('app.shell') 6 | .directive('skLoadingScreen', skLoadingScreen); 7 | 8 | skLoadingScreen.$inject = ['baseUrl', 'appStatusService', 'appSettingsService']; 9 | 10 | function skLoadingScreen(baseUrl, appStatusService, appSettingsService) { 11 | var directive = { 12 | link: link, 13 | restrict: 'E', 14 | templateUrl: baseUrl + 'shell/skLoadingScreen.html' 15 | }; 16 | return directive; 17 | 18 | function link(scope, element, attrs) { 19 | scope.title = appSettingsService.title; 20 | scope.hide = false; 21 | 22 | scope.$watch(function () { 23 | return appStatusService.info.loading; 24 | }, function (value) { 25 | scope.hide = !value; 26 | }); 27 | 28 | } 29 | } 30 | 31 | })(); -------------------------------------------------------------------------------- /Spa/spa/shell/skNavLink.html: -------------------------------------------------------------------------------- 1 | 
  • 2 | 3 | 4 | 7 |
  • -------------------------------------------------------------------------------- /Spa/spa/shell/skNavLink.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | angular 5 | .module('app.shell') 6 | .directive('skNavLink', skNavLink); 7 | 8 | skNavLink.$inject = ['$filter', '$templateRequest', '$compile', '$rootScope', 'baseUrl']; 9 | 10 | function skNavLink($filter, $templateRequest, $compile, $rootScope, baseUrl) { 11 | var directive = { 12 | restrict: 'E', 13 | scope: { 14 | navLink: '=' 15 | }, 16 | replace: true, 17 | link: link 18 | }; 19 | return directive; 20 | 21 | function link(scope, element, attrs) { 22 | $templateRequest(baseUrl + 'shell/skNavLink.html').then(function (result) { 23 | scope.navLinks = scope.$parent.navLinks || scope.$parent.$parent.navLinks; 24 | scope.hasChildren = $filter('filter')(scope.navLinks, { 25 | parent: scope.navLink.name 26 | }).length > 0; 27 | 28 | var template = angular.element(result); 29 | 30 | if (!scope.hasChildren) { 31 | template.children(".child-nav-links").remove(); 32 | } 33 | 34 | var el = $compile(template)(scope); 35 | element.replaceWith(el); 36 | }); 37 | 38 | $rootScope.$on('$routeChangeSuccess', function (event, next, current) { 39 | if (!scope.navLink.parent && next.$$route) { 40 | scope.navLink.isActive = scope.navLink.name === next.$$route.showNav 41 | || scope.navLink.name === next.$$route.parent; 42 | } 43 | }); 44 | } 45 | } 46 | })(); -------------------------------------------------------------------------------- /Spa/spa/shell/skNavLinks.html: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /Spa/spa/shell/skNavLinks.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | angular 5 | .module('app.shell') 6 | .directive('skNavLinks', skNavLinks); 7 | 8 | skNavLinks.$inject = ['$rootScope', '$location', 'baseUrl']; 9 | 10 | function skNavLinks($rootScope, $location, baseUrl) { 11 | var directive = { 12 | link: link, 13 | restrict: 'E', 14 | scope: { 15 | navLinks: '=' 16 | }, 17 | replace: true, 18 | templateUrl: baseUrl + 'shell/skNavLinks.html' 19 | }; 20 | return directive; 21 | 22 | function link(scope, element, attrs) { 23 | scope.isTopLevel = function (link) { 24 | return !link.parent; 25 | }; 26 | 27 | setInitialActive(); 28 | 29 | function setInitialActive() { 30 | if (scope.navLinks && $location.path()) { 31 | var activePath = $location.path().substring(1); 32 | scope.navLinks.forEach(function (navLink) { 33 | navLink.isActive = navLink.url === activePath; 34 | }); 35 | } 36 | } 37 | } 38 | } 39 | })(); -------------------------------------------------------------------------------- /Spa/spa/shell/skTopNav.html: -------------------------------------------------------------------------------- 1 | 
    2 | 24 |
    -------------------------------------------------------------------------------- /Spa/spa/shell/skTopNav.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('app.shell') 6 | .directive('skTopNav', skTopNav); 7 | 8 | skTopNav.$inject = ['appSettingsService', 'navigationService', 'baseUrl']; 9 | 10 | function skTopNav(appSettingsService, navigationService, baseUrl) { 11 | var directive = { 12 | link: link, 13 | restrict: 'E', 14 | replace: true, 15 | templateUrl: baseUrl + 'shell/skTopNav.html' 16 | }; 17 | return directive; 18 | 19 | function link(scope, element, attrs) { 20 | scope.title = appSettingsService.title; 21 | scope.brand = appSettingsService.brand; 22 | scope.links = navigationService.getLinks(); 23 | } 24 | } 25 | 26 | })(); -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | #Secure Starter 2 | 3 | An AngularJS starter kit for ASP.NET which implements authentication and authorization (ASP.NET Identity 2.0.0) to provide: 4 | 5 | * site based and 3rd party user authentication 6 | * local SPA authorization and customization based on role membership 7 | 8 | ##Getting started 9 | 10 | During the database initialization ([ApplicationDbInitializer](https://github.com/Useful-Software-Solutions-Ltd/Angular.Net.SecureStarter/blob/master/Angular.SecureStarter/Models/ApplicationDbInitializer.cs)) two roles are created: 11 | 12 | * administrator 13 | * user 14 | 15 | A user called **Administrator** is also created with the password '**Administrator55$**' and added to both roles. 16 | Edit the initializer if you need to change this, or add more roles and users. 17 | 18 | To get familiar with configuring security on the SPA side of things see the following wiki pages: 19 | * [securing a route](https://github.com/Useful-Software-Solutions-Ltd/Angular.Net.SecureStarter/wiki/Securing-a-route) 20 | * [configuring role based content](https://github.com/Useful-Software-Solutions-Ltd/Angular.Net.SecureStarter/wiki/Role-based-content) 21 | * [setting up an external authentication provider walkthrough](https://github.com/Useful-Software-Solutions-Ltd/Angular.Net.SecureStarter/wiki/Setting-up-an-external-authentication-provider) 22 | 23 | There are a few other features to make life a bit easier which you can read about [here](https://github.com/Useful-Software-Solutions-Ltd/Angular.Net.SecureStarter/wiki/Other-features). 24 | 25 | ##Installation 26 | 27 | You can fork or download this repo. 28 | 29 | It is also available as a Nuget package (you can find it [here](https://www.nuget.org/packages/Angular.SecureStarter)). 30 | In Visual Studio create a new Web API project with the authentication option set to 'individual user accounts'. Then either install the package using the package manager or from to install from the Package Manager Console enter the following command: 31 | 32 | ``` 33 | Install-Package Angular.SecureStarter 34 | ``` 35 | 36 | ##Current status 37 | 38 | The starter kit currently implements the basic authentication functionality equivalent to that found in the Visual Studio 2013 ASP.NET 'Single Page Application'. Future enhancements will (hopefully) include: 39 | * two-factor authentication 40 | * password reset by email 41 | * basic user management 42 | --------------------------------------------------------------------------------