diff --git a/README.md b/README.md index 8f2a9e6..58fa929 100644 --- a/README.md +++ b/README.md @@ -84,3 +84,21 @@ Submit a pull request when you are finished and satisfied with your work. ## License [MIT](http://opensource.org/licenses/MIT) + + +---- +edits by longda below: + + +## Note #1: +At this point, we've reached a critical juncture in our journey. If we were working a big team, we could start dividing things up: + +1. If we had a web app that user's could, um, use to make notes for instance, we could hand that off to a front-end dev to start whipping things out using the stub services rather than REAL services that have to hit a REAL data store. Another example (which could be developed in tandem) would be an admin site where our internal team could start setting up user accounts to use our API. +2. We could start talking to a dba type to start setting up our db and our sprocs, etc. +3. We could also have a middle-tier dev start fleshing out the API calls and the auth and maybe even an ORM or something. +4. Or we could scrap all that and just have a tech lead do it! :boom: + + +## Note #2: +Here's the sample output from the get call as of this point: +{"Id":1,"Title":"Go to the Galaxy Game.","Description":"Head over to Stub Hub Center in Carson, California for a lovely game of fútbol.","IsComplete":false} \ No newline at end of file diff --git a/src/.gitignore b/src/.gitignore new file mode 100644 index 0000000..16b413c --- /dev/null +++ b/src/.gitignore @@ -0,0 +1,182 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +build/ +bld/ +[Bb]in/ +[Oo]bj/ + +# Roslyn cache directories +*.ide/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +#NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding addin-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# If using the old MSBuild-Integrated Package Restore, uncomment this: +#!**/packages/repositories.config + +# Windows Azure Build Output +csx/ +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ \ No newline at end of file diff --git a/src/Notesy.Api/App_Start/NinjectWebCommon.cs b/src/Notesy.Api/App_Start/NinjectWebCommon.cs new file mode 100644 index 0000000..c4d5d17 --- /dev/null +++ b/src/Notesy.Api/App_Start/NinjectWebCommon.cs @@ -0,0 +1,82 @@ +[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(Notesy.Api.App_Start.NinjectWebCommon), "Start")] +[assembly: WebActivatorEx.ApplicationShutdownMethodAttribute(typeof(Notesy.Api.App_Start.NinjectWebCommon), "Stop")] + +namespace Notesy.Api.App_Start +{ + using System; + using System.Web; + + using Microsoft.Web.Infrastructure.DynamicModuleHelper; + + using Ninject; + using Ninject.Web.Common; + + using Notesy.Core.Services.Concrete; + using Notesy.Core.Services.Interfaces; + using Notesy.Core.Services.Stubs; + + public static class NinjectWebCommon + { + private static readonly Bootstrapper bootstrapper = new Bootstrapper(); + + /// + /// Starts the application + /// + public static void Start() + { + DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule)); + DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule)); + bootstrapper.Initialize(CreateKernel); + } + + /// + /// Stops the application. + /// + public static void Stop() + { + bootstrapper.ShutDown(); + } + + /// + /// Creates the kernel that will manage your application. + /// + /// The created kernel. + private static IKernel CreateKernel() + { + var kernel = new StandardKernel(); + try + { + kernel.Bind>().ToMethod(ctx => () => new Bootstrapper().Kernel); + kernel.Bind().To(); + + // Note: Look how easy that is to swap out the fake services (which might not hit a real db) for real ones. I bet we could + // even do that with a config setting or db setting too (or not)! + + //RegisterServices(kernel); + RegisterStubServices(kernel); + return kernel; + } + catch + { + kernel.Dispose(); + throw; + } + } + + /// + /// Load your modules or register your services here! + /// + /// The kernel. + private static void RegisterServices(IKernel kernel) + { + kernel.Bind().To().InRequestScope(); + kernel.Bind().To().InRequestScope(); + } + + private static void RegisterStubServices(IKernel kernel) + { + kernel.Bind().To().InRequestScope(); + kernel.Bind().To().InRequestScope(); + } + } +} diff --git a/src/Notesy.Api/App_Start/RouteConfig.cs b/src/Notesy.Api/App_Start/RouteConfig.cs new file mode 100644 index 0000000..18a7f45 --- /dev/null +++ b/src/Notesy.Api/App_Start/RouteConfig.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.Mvc; +using System.Web.Routing; + +namespace Notesy.Api +{ + public class RouteConfig + { + public static void RegisterRoutes(RouteCollection routes) + { + routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); + + routes.MapRoute( + name: "Default", + url: "{controller}/{action}/{id}", + defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } + ); + } + } +} diff --git a/src/Notesy.Api/Controllers/NoteController.cs b/src/Notesy.Api/Controllers/NoteController.cs new file mode 100644 index 0000000..039ff42 --- /dev/null +++ b/src/Notesy.Api/Controllers/NoteController.cs @@ -0,0 +1,175 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Web; +using System.Web.Mvc; + +using Notesy.Core.Models; +using Notesy.Core.Services.Interfaces; + +namespace Notesy.Api.Controllers +{ + // So, there are a quite a few ways to setup an API. For this one, since it's a quick-hitter, I'm just going to leverage a bunch of stuff + // that's already baked in so we can whip this thing out. + + // For now, calls will come into the NoteController which will be where the authentication goes down. If a call passes auth, then we will + // send the call off to the dependency injected Note Service (which could be a real service or a fake/stub one). This provides us with a + // host of advantages such as being able to isolate auth to the very edge (aka application boundry) and we can then re-use all that delicious + // code we've written in the service that does, you know, actual work. We could then do things like re-use the API internally without auth + // on something akin to a private API or even call it from inside that Notesy.Web project (which could be a brochure site, a web app, etc). + + // Additionally, auth can be done in many ways. We could do OAuth if we were leveraging an external service (e.g. we had folks sign up for + // API access with Twitter). I'm going to do my patented "fake auth" which will illustrate a "signed" API similar to this real world + // example: http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-creating-signed-url-canned-policy.html + // I'm going to do this inline to save time but if this were a real life app I'd look into using an Action Filter or possibly an + // existing library off nuget. Or a base controller. Or an extension method. Or a helper. Or a combination of these. + + // TLDR; Everything always depends. Real world constraints might change how you architect things. + + public class NoteController : Controller + { + private readonly INoteService noteService; + private readonly IApiUserService apiUserService; + + public NoteController(INoteService noteService, IApiUserService apiUserService) + { + this.noteService = noteService; + this.apiUserService = apiUserService; + } + + // Note: This will be at something like: http://localhost:63185/note/save + // TODO: since this is taking in a note model we'll need to make sure we're serializing the input properly before it hits the api + + /// + /// Save a Note. + /// + /// The note to save. + /// The api key of the user request. + /// A rotating integer to uniquely identify this request. Usually just use current ticks count. There are a number of ways to do this. + /// Signature for this api request. + /// + public ActionResult Save(Note input, string apikey = null, int? callId = null, string signature = null) + { + if (!ApiHelper.ValidateAuth(ApiHelper.ToJsonString(input), apikey, signature)) { return new HttpUnauthorizedResult(); } + + var result = noteService.SaveNote(input); + + return Json(input, JsonRequestBehavior.AllowGet); + } + + public ActionResult Get(int id, string apikey = null, int? callId = null, string signature = null) + { + // basic logic for this architecture (could be different) + // 1) validate the auth on the incoming request + // 2) next we need to get the api user by apikey (oops - we need to write that!) + // 3) next we need to get the note + // 4) last we need to check that the api user is the owner of this note + + // obviously lots of decisions here... this might have been easier if we used + // an orm. we also could have pushed this logic one level lower so we could + // reuse it. this will be good for now though. + + if (!ApiHelper.ValidateAuth(id.ToString(), apikey, callId.Value.ToString(), signature)) { return new HttpUnauthorizedResult(); } + + var user = apiUserService.GetApiUserByApiKey(apikey); + var note = noteService.GetNote(id); + + if (user.Id == note.ApiUserId) + { + return Json(note, JsonRequestBehavior.AllowGet); + } + + // TODO: Have to think about what to do with errors. + return Json(note, JsonRequestBehavior.AllowGet); + } + + public ActionResult Delete(int id, string apikey = null, int? callId = null, string signature = null) + { + if (!ApiHelper.ValidateAuth(id.ToString(), apikey, callId.Value.ToString(), signature)) { return new HttpUnauthorizedResult(); } + + var result = noteService.DeleteNote(id); + + return Json(result, JsonRequestBehavior.AllowGet); + } + } + + public static class ApiHelper + { + // TODO: the following methods would be good candidates for relocation to a helper or other logical place. + // NOTE: Need to start making these public now for testing. It would be better to put this is in it's own + // helper class or something but we're running low on time (for now at least). + + public static bool ValidateAuth(string apiKey, string signatureToCheck, params string[] args) + { + // TODO: actual auth stuff + // 1) lookup api user + // 2) generate signature of inputs + // 3) compare generated signature to incoming signature + // 4) if valid, return true, otherwise false - note there could be a number of other things to check here: api usage, incoming IP, etc. + + return true; + } + + /// + /// + /// + /// + /// + /// + public static bool DoSignaturesMatch(ApiUser apiUser, string signature, params string[] args) + { + // how to generate a signature: + // 1) concat all the call parameters into one string (see string array above) + // 2) run some agreed upon encryption algorithm on concat string using the shared secret associated with the apikey => apiuser for this request + + // IMPORTANT: for this to actually work correctly we need to store the call id so that api calls cannot be replayed + // NOTE: remember this is just sort of a quick homebrew system. you'd almost certainly want to reuse an appropriate auth library. + // TODO: i think i got that right, double-check once implemented and document any changes here + + var sb = new StringBuilder(); + foreach (var arg in args) + { + sb.Append(arg); + } + sb.Append(apiUser.ApiSecret); + var gen = ApiHelper.GetHash(sb.ToString()); + + return gen == signature; + } + + public static string ToJsonString(object input) + { + // here is where we'd serialize the object out to a string containing a json object + return ""; + } + + private static HashAlgorithm HashProvider = new SHA1Managed(); + + public static string GetHash(string input) + { + byte[] inputBytes = Encoding.UTF8.GetBytes(input); + byte[] data = HashProvider.ComputeHash(inputBytes); + var output = ByteArrayToHex(data); + + return output; + } + + // http://stackoverflow.com/questions/311165/how-do-you-convert-byte-array-to-hexadecimal-string-and-vice-versa + public static string ByteArrayToHex(byte[] barray) + { + char[] c = new char[barray.Length * 2]; + byte b; + for (int i = 0; i < barray.Length; ++i) + { + b = ((byte)(barray[i] >> 4)); + c[i * 2] = (char)(b > 9 ? b + 0x37 : b + 0x30); + b = ((byte)(barray[i] & 0xF)); + c[i * 2 + 1] = (char)(b > 9 ? b + 0x37 : b + 0x30); + } + + return new string(c); + } + } +} \ No newline at end of file diff --git a/src/Notesy.Api/Global.asax b/src/Notesy.Api/Global.asax new file mode 100644 index 0000000..606815a --- /dev/null +++ b/src/Notesy.Api/Global.asax @@ -0,0 +1 @@ +<%@ Application Codebehind="Global.asax.cs" Inherits="Notesy.Api.MvcApplication" Language="C#" %> diff --git a/src/Notesy.Api/Global.asax.cs b/src/Notesy.Api/Global.asax.cs new file mode 100644 index 0000000..0e4389c --- /dev/null +++ b/src/Notesy.Api/Global.asax.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.Mvc; +using System.Web.Routing; + +namespace Notesy.Api +{ + public class MvcApplication : System.Web.HttpApplication + { + protected void Application_Start() + { + AreaRegistration.RegisterAllAreas(); + RouteConfig.RegisterRoutes(RouteTable.Routes); + } + } +} diff --git a/src/Notesy.Api/Notesy.Api.csproj b/src/Notesy.Api/Notesy.Api.csproj new file mode 100644 index 0000000..7830712 --- /dev/null +++ b/src/Notesy.Api/Notesy.Api.csproj @@ -0,0 +1,159 @@ + + + + + Debug + AnyCPU + + + 2.0 + {291D09DB-7DCB-41DB-B634-942B1F8BC545} + {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + Notesy.Api + Notesy.Api + v4.5 + true + + + + + + + true + full + false + bin\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\ + TRACE + prompt + 4 + + + + + ..\packages\Ninject.3.2.2.0\lib\net45-full\Ninject.dll + + + ..\packages\Ninject.Web.Common.3.2.0.0\lib\net45-full\Ninject.Web.Common.dll + + + ..\packages\Ninject.MVC5.3.2.1.0\lib\net45-full\Ninject.Web.Mvc.dll + + + + + + + + + + + + + + + + + + + ..\packages\WebActivatorEx.2.0\lib\net40\WebActivatorEx.dll + + + + + True + ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll + + + ..\packages\Microsoft.AspNet.Razor.3.0.0\lib\net45\System.Web.Razor.dll + + + ..\packages\Microsoft.AspNet.Webpages.3.0.0\lib\net45\System.Web.Webpages.dll + + + ..\packages\Microsoft.AspNet.Webpages.3.0.0\lib\net45\System.Web.Webpages.Deployment.dll + + + ..\packages\Microsoft.AspNet.Webpages.3.0.0\lib\net45\System.Web.Webpages.Razor.dll + + + ..\packages\Microsoft.AspNet.Webpages.3.0.0\lib\net45\System.Web.Helpers.dll + + + ..\packages\Microsoft.AspNet.Mvc.5.0.0\lib\net45\System.Web.Mvc.dll + + + + + + + + + + + + Global.asax + + + + + + + + Web.config + + + Web.config + + + + + + + + {5dd8ffda-34c8-4f81-8740-20e29bfc4e90} + Notesy.Core + + + + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + + + + + + True + True + 0 + / + http://localhost:63185/ + False + False + + + False + + + + + + \ No newline at end of file diff --git a/src/Notesy.Api/Properties/AssemblyInfo.cs b/src/Notesy.Api/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..6e121e3 --- /dev/null +++ b/src/Notesy.Api/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Notesy.Api")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Notesy.Api")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("86bfb859-2218-496a-b8e5-e250645b26ba")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/Notesy.Api/Views/web.config b/src/Notesy.Api/Views/web.config new file mode 100644 index 0000000..09da0d0 --- /dev/null +++ b/src/Notesy.Api/Views/web.config @@ -0,0 +1,34 @@ + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Notesy.Api/Web.Debug.config b/src/Notesy.Api/Web.Debug.config new file mode 100644 index 0000000..f7c5612 --- /dev/null +++ b/src/Notesy.Api/Web.Debug.config @@ -0,0 +1,30 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/Notesy.Api/Web.Release.config b/src/Notesy.Api/Web.Release.config new file mode 100644 index 0000000..52c6bbe --- /dev/null +++ b/src/Notesy.Api/Web.Release.config @@ -0,0 +1,31 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/Notesy.Api/Web.config b/src/Notesy.Api/Web.config new file mode 100644 index 0000000..2cd7529 --- /dev/null +++ b/src/Notesy.Api/Web.config @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Notesy.Api/packages.config b/src/Notesy.Api/packages.config new file mode 100644 index 0000000..07a0910 --- /dev/null +++ b/src/Notesy.Api/packages.config @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Notesy.Core/Models/ApiUser.cs b/src/Notesy.Core/Models/ApiUser.cs new file mode 100644 index 0000000..cede989 --- /dev/null +++ b/src/Notesy.Core/Models/ApiUser.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Notesy.Core.Models +{ + public class ApiUser + { + public int Id { get; set; } + public string Name { get; set; } + public string ApiKey { get; set; } + public string ApiSecret { get; set; } + public DateTime DateCreated { get; set; } + } +} diff --git a/src/Notesy.Core/Models/Note.cs b/src/Notesy.Core/Models/Note.cs new file mode 100644 index 0000000..1b96211 --- /dev/null +++ b/src/Notesy.Core/Models/Note.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Notesy.Core.Models +{ + // At this point, if we were using a true ORM we could be linking our models and defining their relationships (such as NHibernate or Entity Framework, etc). You + // could do some of this in code (rather than a config) with Fluent NHibernate or similar library. For a huge example, see Sharp Architecture: https://github.com/sharparchitecture/Sharp-Architecture/tree/master/Solutions/SharpArch.NHibernate + + public class Note + { + public int Id { get; set; } + public string Title { get; set; } + public string Description { get; set; } + public bool IsComplete { get; set; } + public int ApiUserId { get; set; } // this is where we could define an ORM relation ship... it'd be something more like: public ApiUser ApiUser { get; set; }, though it would need to be "glued" together with a true ORM + public DateTime DateCreated { get; set; } + + public Note() + { + IsComplete = false; // this defaults to false but let's be explicit + DateCreated = DateTime.UtcNow; + } + } +} diff --git a/src/Notesy.Core/Notesy.Core.csproj b/src/Notesy.Core/Notesy.Core.csproj new file mode 100644 index 0000000..e4c356a --- /dev/null +++ b/src/Notesy.Core/Notesy.Core.csproj @@ -0,0 +1,67 @@ + + + + + Debug + AnyCPU + {5DD8FFDA-34C8-4F81-8740-20E29BFC4E90} + Library + Properties + Notesy.Core + Notesy.Core + v4.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\Dapper.1.29\lib\net45\Dapper.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Notesy.Core/Properties/AssemblyInfo.cs b/src/Notesy.Core/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..9ce2c37 --- /dev/null +++ b/src/Notesy.Core/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("notesy")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("notesy")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("90973b19-9c9b-4347-9217-bd533cea0d45")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/Notesy.Core/Services/Concrete/ApiUserService.cs b/src/Notesy.Core/Services/Concrete/ApiUserService.cs new file mode 100644 index 0000000..9c3a5e0 --- /dev/null +++ b/src/Notesy.Core/Services/Concrete/ApiUserService.cs @@ -0,0 +1,139 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Data.SqlClient; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using Dapper; +using Notesy.Core.Models; +using Notesy.Core.Services.Interfaces; + +namespace Notesy.Core.Services.Concrete +{ + public class ApiUserService : IApiUserService + { + public ApiUser GetApiUser(int id) + { + var output = new ApiUser(); + + var sql = @"SELECT + [Id] + ,[Name] + ,[ApiKey] + ,[ApiSecret] + ,[DateCreated] + FROM + [dbo].[ApiUser] + WHERE + [Id] = @Id"; + + using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["NOTESY_CORE"].ConnectionString)) + { + connection.Open(); + var users = connection.Query(sql, new { Id = id }); + output = users.First(); + } + + return output; + } + + public ApiUser SaveApiUser(ApiUser input) + { + var output = new ApiUser(); + + var insert = @"INSERT INTO + [dbo].[ApiUser] + ([Name] + ,[ApiKey] + ,[ApiSecret] + ,[DateCreated]) + VALUES + (@Name, + @ApiKey, + @ApiSecret, + @DateCreated) + + SELECT SCOPE_IDENTITY()"; + + var update = @"UPDATE + [dbo].[ApiUser] + SET + [Name] = @Name, + [ApiKey] = @ApiKey, + [ApiSecret] = @ApiSecret, + [DateCreated] = @DateCreated + WHERE + [Id] = @Id"; + + if (input.Id == 0) + { + // insert + using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["NOTESY_CORE"].ConnectionString)) + { + connection.Open(); + var result = connection.Query(insert, new { Name = input.Name, ApiKey = input.ApiKey, ApiSecret = input.ApiSecret, DateCreated = input.DateCreated }); + output = input; + output.Id = result.First(); + } + } + else + { + // update + using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["NOTESY_CORE"].ConnectionString)) + { + connection.Open(); + var result = connection.Execute(update, new { Name = input.Name, ApiKey = input.ApiKey, ApiSecret = input.ApiSecret, DateCreated = input.DateCreated }); + output = input; + } + } + + return output; + } + + public ApiUser DeleteApiUser(int id) + { + var output = GetApiUser(id); + + var sql = @"DELETE FROM + [dbo].[ApiUser] + WHERE + [Id] = @Id"; + + using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["NOTESY_CORE"].ConnectionString)) + { + connection.Open(); + var result = connection.Execute(sql, new { Id = id }); + } + + return output; + } + + + public ApiUser GetApiUserByApiKey(string apiKey) + { + var output = new ApiUser(); + + var sql = @"SELECT + [Id] + ,[Name] + ,[ApiKey] + ,[ApiSecret] + ,[DateCreated] + FROM + [dbo].[ApiUser] + WHERE + [ApiKey] = @ApiKey"; + + using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["NOTESY_CORE"].ConnectionString)) + { + connection.Open(); + var result = connection.Execute(sql, new { ApiKey = apiKey }); + } + + return output; + } + } +} diff --git a/src/Notesy.Core/Services/Concrete/NoteService.cs b/src/Notesy.Core/Services/Concrete/NoteService.cs new file mode 100644 index 0000000..79f0f11 --- /dev/null +++ b/src/Notesy.Core/Services/Concrete/NoteService.cs @@ -0,0 +1,128 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Data.SqlClient; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using Dapper; +using Notesy.Core.Models; +using Notesy.Core.Services.Interfaces; + +namespace Notesy.Core.Services.Concrete +{ + public class NoteService : INoteService + { + // https://github.com/StackExchange/dapper-dot-net#performance-of-select-mapping-over-500-iterations---poco-serialization + // Not exactly the best reason but there is something to say about dapper given it's simplicity and speed. We'll use it here. + // At this point, we could also just connect to a cloud service or any other data store and the rest of the app wouldn't need to know. It doesn't + // have to be a relational database. + + // ASSUMPTIONS: + // * All incoming inputs are valid. + // * New objects have an id of 0. + + public Note GetNote(int id) + { + var output = new Note(); + + // In most cases, you'd want to at least consider sprocs here rather than raw sql. + var sql = @"SELECT + [Id] + ,[Title] + ,[Description] + ,[IsComplete] + ,[ApiUserId] + ,[DateCreated] + FROM + [dbo].[Note] + WHERE + [Id] = @Id"; + + using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["NOTESY_CORE"].ConnectionString)) + { + connection.Open(); + var notes = connection.Query(sql, new { Id = id }); + output = notes.First(); // TODO: lots to talk about in this line of code + } + + return output; + } + + public Note SaveNote(Note input) + { + var output = new Note(); + + var insert = @"INSERT INTO + [dbo].[Note] + ([Title] + ,[Description] + ,[IsComplete] + ,[ApiUserId] + ,[DateCreated]) + VALUES + (@Title, + @Description, + @IsComplete, + @ApiUserId, + @DateCreated) + + SELECT SCOPE_IDENTITY()"; + + var update = @"UPDATE + [dbo].[Note] + SET + [Title] = @Title, + [Description] = @Description, + [IsComplete] = @IsComplete, + [ApiUserId] = @ApiUserId, + [DateCreated] = @DateCreated + WHERE + [Id] = @Id"; + + if (input.Id == 0) + { + // insert + using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["NOTESY_CORE"].ConnectionString)) + { + connection.Open(); + var result = connection.Query(insert, new { Title = input.Title, Description = input.Description, IsComplete = input.IsComplete, ApiUserId = input.ApiUserId, DateCreated = input.DateCreated }); + output = input; + output.Id = result.First(); + } + } + else + { + // update + using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["NOTESY_CORE"].ConnectionString)) + { + connection.Open(); + var result = connection.Execute(update, new { Id = input.Id, Title = input.Title, Description = input.Description, IsComplete = input.IsComplete, ApiUserId = input.ApiUserId, DateCreated = input.DateCreated }); + output = input; + } + } + + return output; + } + + public Note DeleteNote(int id) + { + var output = GetNote(id); + + var sql = @"DELETE FROM + [dbo].[Note] + WHERE + [Id] = @Id"; + + using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["NOTESY_CORE"].ConnectionString)) + { + connection.Open(); + var result = connection.Execute(sql, new { Id = id }); + } + + return output; + } + } +} diff --git a/src/Notesy.Core/Services/Interfaces/IApiUserService.cs b/src/Notesy.Core/Services/Interfaces/IApiUserService.cs new file mode 100644 index 0000000..cdb950a --- /dev/null +++ b/src/Notesy.Core/Services/Interfaces/IApiUserService.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using Notesy.Core.Models; + +namespace Notesy.Core.Services.Interfaces +{ + public interface IApiUserService + { + ApiUser GetApiUser(int id); + ApiUser SaveApiUser(ApiUser input); + ApiUser DeleteApiUser(int id); + ApiUser GetApiUserByApiKey(string apiKey); + } +} diff --git a/src/Notesy.Core/Services/Interfaces/INoteService.cs b/src/Notesy.Core/Services/Interfaces/INoteService.cs new file mode 100644 index 0000000..ad2e07c --- /dev/null +++ b/src/Notesy.Core/Services/Interfaces/INoteService.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using Notesy.Core.Models; + +namespace Notesy.Core.Services.Interfaces +{ + public interface INoteService + { + Note GetNote(int id); + Note SaveNote(Note input); + Note DeleteNote(int id); + } +} diff --git a/src/Notesy.Core/Services/Stubs/ApiUserServiceStub.cs b/src/Notesy.Core/Services/Stubs/ApiUserServiceStub.cs new file mode 100644 index 0000000..3b109e1 --- /dev/null +++ b/src/Notesy.Core/Services/Stubs/ApiUserServiceStub.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using Notesy.Core.Models; +using Notesy.Core.Services.Interfaces; + +namespace Notesy.Core.Services.Stubs +{ + public class ApiUserServiceStub : IApiUserService + { + private string API_KEY = "BEF0A331-C388-43D2-96A0-6B94838F87E0"; + private string API_SECRET = "01D25503-C5C4-46A3-B99A-8BE8BB2AF0D7"; + + public ApiUser GetApiUser(int id) + { + return new ApiUser() + { + ApiKey = API_KEY, + ApiSecret = API_SECRET, + Id = id, + Name = "Famous Dave" + }; + } + + public ApiUser SaveApiUser(ApiUser input) + { + // if id = 0 (or null if you're using a nullable type) then this is new so insert, otherwise it's an update (aka an upsert) + return input; + } + + public ApiUser DeleteApiUser(int id) + { + return new ApiUser() + { + ApiKey = API_KEY, + ApiSecret = API_SECRET, + Id = id, + Name = "Famous Dave" + }; + } + + public ApiUser GetApiUserByApiKey(string apiKey) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/Notesy.Core/Services/Stubs/NoteServiceStub.cs b/src/Notesy.Core/Services/Stubs/NoteServiceStub.cs new file mode 100644 index 0000000..6ad6f5e --- /dev/null +++ b/src/Notesy.Core/Services/Stubs/NoteServiceStub.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using Notesy.Core.Models; +using Notesy.Core.Services.Interfaces; + +namespace Notesy.Core.Services.Stubs +{ + public class NoteServiceStub : INoteService + { + public Note GetNote(int id) + { + return new Note() + { + Id = id, + Title = "Go to the Galaxy Game.", + Description = "Head over to Stub Hub Center in Carson, California for a lovely game of fútbol." + }; + } + + public Note SaveNote(Note input) + { + if (input.Id == 0) { input.Id = 456; } + + return input; + } + + public Note DeleteNote(int id) + { + return new Note() + { + Id = id, + Title = "Go to the Galaxy Game.", + Description = "Head over to Stub Hub Center in Carson, California for a lovely game of fútbol." + }; + } + } +} diff --git a/src/Notesy.Core/packages.config b/src/Notesy.Core/packages.config new file mode 100644 index 0000000..82a4f88 --- /dev/null +++ b/src/Notesy.Core/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/Notesy.Database/Notesy.Database.sln b/src/Notesy.Database/Notesy.Database.sln new file mode 100644 index 0000000..f11f3ef --- /dev/null +++ b/src/Notesy.Database/Notesy.Database.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{00D1A9C2-B5F0-4AF3-8072-F6C62B433612}") = "Notesy.Database", "Notesy.Database.sqlproj", "{99A761F7-FBAF-435A-A468-AACC24A7F4E9}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {99A761F7-FBAF-435A-A468-AACC24A7F4E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {99A761F7-FBAF-435A-A468-AACC24A7F4E9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {99A761F7-FBAF-435A-A468-AACC24A7F4E9}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {99A761F7-FBAF-435A-A468-AACC24A7F4E9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {99A761F7-FBAF-435A-A468-AACC24A7F4E9}.Release|Any CPU.Build.0 = Release|Any CPU + {99A761F7-FBAF-435A-A468-AACC24A7F4E9}.Release|Any CPU.Deploy.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/Notesy.Database/Notesy.Database.sqlproj b/src/Notesy.Database/Notesy.Database.sqlproj new file mode 100644 index 0000000..af4f860 --- /dev/null +++ b/src/Notesy.Database/Notesy.Database.sqlproj @@ -0,0 +1,69 @@ + + + + + Debug + AnyCPU + Notesy.Database + 2.0 + 4.1 + {99a761f7-fbaf-435a-a468-aacc24a7f4e9} + Microsoft.Data.Tools.Schema.Sql.Sql110DatabaseSchemaProvider + Database + + + Notesy.Database + Notesy.Database + 1033,CI + BySchemaAndSchemaType + True + v4.5 + CS + Properties + False + True + True + SQL_Latin1_General_CP1_CI_AS + PRIMARY + + + bin\Release\ + $(MSBuildProjectName).sql + False + pdbonly + true + false + true + prompt + 4 + + + bin\Debug\ + $(MSBuildProjectName).sql + false + true + full + false + true + true + prompt + 4 + + + + 10.0 + + True + 10.0 + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Notesy.Database/dbo/Tables/ApiUser.sql b/src/Notesy.Database/dbo/Tables/ApiUser.sql new file mode 100644 index 0000000..902375b --- /dev/null +++ b/src/Notesy.Database/dbo/Tables/ApiUser.sql @@ -0,0 +1,9 @@ +CREATE TABLE [dbo].[ApiUser] ( + [Id] INT IDENTITY (1, 1) NOT NULL, + [Name] NVARCHAR (256) NOT NULL, + [ApiKey] NVARCHAR (1024) NOT NULL, + [ApiSecret] NVARCHAR (1024) NOT NULL, + [DateCreated] DATETIME CONSTRAINT [DF_ApiUser_DateCreated] DEFAULT (getutcdate()) NOT NULL, + CONSTRAINT [PK_ApiUser] PRIMARY KEY CLUSTERED ([Id] ASC) +); + diff --git a/src/Notesy.Database/dbo/Tables/Note.sql b/src/Notesy.Database/dbo/Tables/Note.sql new file mode 100644 index 0000000..f408b2d --- /dev/null +++ b/src/Notesy.Database/dbo/Tables/Note.sql @@ -0,0 +1,11 @@ +CREATE TABLE [dbo].[Note] ( + [Id] INT IDENTITY (1, 1) NOT NULL, + [Title] NVARCHAR (512) NULL, + [Description] NVARCHAR (2048) NULL, + [IsComplete] BIT CONSTRAINT [DF_Note_IsComplete] DEFAULT ((0)) NOT NULL, + [ApiUserId] INT NOT NULL, + [DateCreated] DATETIME CONSTRAINT [DF_Note_DateCreated] DEFAULT (getutcdate()) NOT NULL, + CONSTRAINT [PK_Note] PRIMARY KEY CLUSTERED ([Id] ASC), + CONSTRAINT [FK_Note_ApiUser] FOREIGN KEY ([ApiUserId]) REFERENCES [dbo].[ApiUser] ([Id]) +); + diff --git a/src/Notesy.Tests/Api/ApiHelperTests.cs b/src/Notesy.Tests/Api/ApiHelperTests.cs new file mode 100644 index 0000000..9a8ce35 --- /dev/null +++ b/src/Notesy.Tests/Api/ApiHelperTests.cs @@ -0,0 +1,50 @@ +using System; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +using Notesy.Api.Controllers; // helper in a controler... starting to get wonky +using Notesy.Core.Models; + +namespace Notesy.Tests.Api +{ + [TestClass] + public class ApiHelperTests + { + [TestMethod] + public void TestDoSignaturesMatch() + { + int id = 1; + string apikey = "BEF0A331-C388-43D2-96A0-6B94838F87E0"; + int? callId = 123; + string apisecret = "01D25503-C5C4-46A3-B99A-8BE8BB2AF0D7"; + + string inputs = string.Format("{0}{1}{2}{3}", id, apikey, callId, apisecret); + string signature = ApiHelper.GetHash(inputs); + var user = new ApiUser() + { + Id = id, + ApiKey = apikey, + ApiSecret = apisecret, + Name = "Does not matter" + }; + + var result = ApiHelper.DoSignaturesMatch(user, signature, id.ToString(), apikey, callId.ToString()); + + Assert.IsTrue(result); + } + + [TestMethod] + public void TestGetHash() + { + int id = 1; + string apikey = "BEF0A331-C388-43D2-96A0-6B94838F87E0"; + int? callId = 123; + string apisecret = "01D25503-C5C4-46A3-B99A-8BE8BB2AF0D7"; + + string inputs = string.Format("{0}{1}{2}{3}", id, apikey, callId, apisecret); + string signature = ApiHelper.GetHash(inputs); + + Assert.IsNotNull(signature); + Assert.AreEqual("9660A2B557FB0E3D8110C69F197944EBECCD8FFB", signature); + } + } +} diff --git a/src/Notesy.Tests/App.config b/src/Notesy.Tests/App.config new file mode 100644 index 0000000..1801f64 --- /dev/null +++ b/src/Notesy.Tests/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/Notesy.Tests/Core/Services/NoteServiceTests.cs b/src/Notesy.Tests/Core/Services/NoteServiceTests.cs new file mode 100644 index 0000000..1a3ac3c --- /dev/null +++ b/src/Notesy.Tests/Core/Services/NoteServiceTests.cs @@ -0,0 +1,25 @@ +using System; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +using Notesy.Core.Models; +using Notesy.Core.Services.Concrete; + +namespace Notesy.Tests.Core.Services +{ + [TestClass] + public class NoteServiceTests + { + private NoteService svc = new NoteService(); + + [TestMethod] + public void TestNoteInsert() + { + var n = new Note() { ApiUserId = 1, Description = "Go to Santa Monica Pier and watch Dr. Who", Title = string.Format("[{0}] Dr Who @ the beach.", DateTime.UtcNow.Ticks) }; + + var result = svc.SaveNote(n); + + Assert.IsNotNull(result); + Assert.IsTrue(result.Id != 0); + } + } +} diff --git a/src/Notesy.Tests/Notesy.Tests.csproj b/src/Notesy.Tests/Notesy.Tests.csproj new file mode 100644 index 0000000..416f251 --- /dev/null +++ b/src/Notesy.Tests/Notesy.Tests.csproj @@ -0,0 +1,98 @@ + + + + Debug + AnyCPU + {AE724AF0-7C54-427D-87F8-AD0E9056EE25} + Library + Properties + Notesy.Tests + Notesy.Tests + v4.5 + 512 + {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages + False + UnitTest + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + {291d09db-7dcb-41db-b634-942b1f8bc545} + Notesy.Api + + + {5dd8ffda-34c8-4f81-8740-20e29bfc4e90} + Notesy.Core + + + + + + + + False + + + False + + + False + + + False + + + + + + + + \ No newline at end of file diff --git a/src/Notesy.Tests/Properties/AssemblyInfo.cs b/src/Notesy.Tests/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..f6a834a --- /dev/null +++ b/src/Notesy.Tests/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Notesy.Tests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Notesy.Tests")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("94535b77-6e32-47d2-bd23-959d5aaa29ef")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/Notesy.Web/App_Start/RouteConfig.cs b/src/Notesy.Web/App_Start/RouteConfig.cs new file mode 100644 index 0000000..ac4ee7d --- /dev/null +++ b/src/Notesy.Web/App_Start/RouteConfig.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.Mvc; +using System.Web.Routing; + +namespace Notesy.Web +{ + public class RouteConfig + { + public static void RegisterRoutes(RouteCollection routes) + { + routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); + + routes.MapRoute( + name: "Default", + url: "{controller}/{action}/{id}", + defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } + ); + } + } +} diff --git a/src/Notesy.Web/Global.asax b/src/Notesy.Web/Global.asax new file mode 100644 index 0000000..5dbaa50 --- /dev/null +++ b/src/Notesy.Web/Global.asax @@ -0,0 +1 @@ +<%@ Application Codebehind="Global.asax.cs" Inherits="Notesy.Web.MvcApplication" Language="C#" %> diff --git a/src/Notesy.Web/Global.asax.cs b/src/Notesy.Web/Global.asax.cs new file mode 100644 index 0000000..c5b4c06 --- /dev/null +++ b/src/Notesy.Web/Global.asax.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.Mvc; +using System.Web.Routing; + +namespace Notesy.Web +{ + public class MvcApplication : System.Web.HttpApplication + { + protected void Application_Start() + { + AreaRegistration.RegisterAllAreas(); + RouteConfig.RegisterRoutes(RouteTable.Routes); + } + } +} diff --git a/src/Notesy.Web/Notesy.Web.csproj b/src/Notesy.Web/Notesy.Web.csproj new file mode 100644 index 0000000..4e87ddd --- /dev/null +++ b/src/Notesy.Web/Notesy.Web.csproj @@ -0,0 +1,141 @@ + + + + + Debug + AnyCPU + + + 2.0 + {7CAD7D06-49CF-4143-BBB0-1A884EC20D57} + {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + Notesy.Web + Notesy.Web + v4.5 + true + + + + + + + true + full + false + bin\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + True + ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll + + + ..\packages\Microsoft.AspNet.Razor.3.0.0\lib\net45\System.Web.Razor.dll + + + ..\packages\Microsoft.AspNet.Webpages.3.0.0\lib\net45\System.Web.Webpages.dll + + + ..\packages\Microsoft.AspNet.Webpages.3.0.0\lib\net45\System.Web.Webpages.Deployment.dll + + + ..\packages\Microsoft.AspNet.Webpages.3.0.0\lib\net45\System.Web.Webpages.Razor.dll + + + ..\packages\Microsoft.AspNet.Webpages.3.0.0\lib\net45\System.Web.Helpers.dll + + + ..\packages\Microsoft.AspNet.Mvc.5.0.0\lib\net45\System.Web.Mvc.dll + + + + + + + + + + Global.asax + + + + + + + + Web.config + + + Web.config + + + + + + + + + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + + + + + + True + True + 0 + / + http://localhost:63163/ + False + False + + + False + + + + + + \ No newline at end of file diff --git a/src/Notesy.Web/Properties/AssemblyInfo.cs b/src/Notesy.Web/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..be59c62 --- /dev/null +++ b/src/Notesy.Web/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Notesy.Web")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Notesy.Web")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("eb19e232-c2d1-46aa-b227-d5acba68b72d")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/Notesy.Web/Views/web.config b/src/Notesy.Web/Views/web.config new file mode 100644 index 0000000..6dd92c5 --- /dev/null +++ b/src/Notesy.Web/Views/web.config @@ -0,0 +1,34 @@ + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Notesy.Web/Web.Debug.config b/src/Notesy.Web/Web.Debug.config new file mode 100644 index 0000000..f7c5612 --- /dev/null +++ b/src/Notesy.Web/Web.Debug.config @@ -0,0 +1,30 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/Notesy.Web/Web.Release.config b/src/Notesy.Web/Web.Release.config new file mode 100644 index 0000000..52c6bbe --- /dev/null +++ b/src/Notesy.Web/Web.Release.config @@ -0,0 +1,31 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/Notesy.Web/Web.config b/src/Notesy.Web/Web.config new file mode 100644 index 0000000..67ea100 --- /dev/null +++ b/src/Notesy.Web/Web.config @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + diff --git a/src/Notesy.Web/packages.config b/src/Notesy.Web/packages.config new file mode 100644 index 0000000..57f2336 --- /dev/null +++ b/src/Notesy.Web/packages.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/notesy.sln b/src/notesy.sln new file mode 100644 index 0000000..2e240d3 --- /dev/null +++ b/src/notesy.sln @@ -0,0 +1,38 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Notesy.Web", "Notesy.Web\Notesy.Web.csproj", "{7CAD7D06-49CF-4143-BBB0-1A884EC20D57}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Notesy.Api", "Notesy.Api\Notesy.Api.csproj", "{291D09DB-7DCB-41DB-B634-942B1F8BC545}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Notesy.Core", "Notesy.Core\Notesy.Core.csproj", "{5DD8FFDA-34C8-4F81-8740-20E29BFC4E90}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Notesy.Tests", "Notesy.Tests\Notesy.Tests.csproj", "{AE724AF0-7C54-427D-87F8-AD0E9056EE25}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7CAD7D06-49CF-4143-BBB0-1A884EC20D57}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7CAD7D06-49CF-4143-BBB0-1A884EC20D57}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7CAD7D06-49CF-4143-BBB0-1A884EC20D57}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7CAD7D06-49CF-4143-BBB0-1A884EC20D57}.Release|Any CPU.Build.0 = Release|Any CPU + {291D09DB-7DCB-41DB-B634-942B1F8BC545}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {291D09DB-7DCB-41DB-B634-942B1F8BC545}.Debug|Any CPU.Build.0 = Debug|Any CPU + {291D09DB-7DCB-41DB-B634-942B1F8BC545}.Release|Any CPU.ActiveCfg = Release|Any CPU + {291D09DB-7DCB-41DB-B634-942B1F8BC545}.Release|Any CPU.Build.0 = Release|Any CPU + {5DD8FFDA-34C8-4F81-8740-20E29BFC4E90}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5DD8FFDA-34C8-4F81-8740-20E29BFC4E90}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5DD8FFDA-34C8-4F81-8740-20E29BFC4E90}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5DD8FFDA-34C8-4F81-8740-20E29BFC4E90}.Release|Any CPU.Build.0 = Release|Any CPU + {AE724AF0-7C54-427D-87F8-AD0E9056EE25}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AE724AF0-7C54-427D-87F8-AD0E9056EE25}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AE724AF0-7C54-427D-87F8-AD0E9056EE25}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AE724AF0-7C54-427D-87F8-AD0E9056EE25}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal