diff --git a/eFormAPI/eFormAPI/App_Start/AutofacConfig.cs b/eFormAPI/eFormAPI/App_Start/AutofacConfig.cs index 1d9090fbf3..6bb27b4df1 100644 --- a/eFormAPI/eFormAPI/App_Start/AutofacConfig.cs +++ b/eFormAPI/eFormAPI/App_Start/AutofacConfig.cs @@ -12,16 +12,12 @@ public static class AutofacConfig public static void ConfigureContainer() { var builder = new ContainerBuilder(); - // Get your HttpConfiguration. var config = GlobalConfiguration.Configuration; - // Register your Web API controllers. builder.RegisterApiControllers(Assembly.GetExecutingAssembly()); - // OPTIONAL: Register the Autofac filter provider. builder.RegisterWebApiFilterProvider(config); - // Set the dependency resolver to be Autofac. Container = builder.Build(); } diff --git a/eFormAPI/eFormAPI/App_Start/Startup.Auth.cs b/eFormAPI/eFormAPI/App_Start/Startup.Auth.cs new file mode 100644 index 0000000000..bf0a631508 --- /dev/null +++ b/eFormAPI/eFormAPI/App_Start/Startup.Auth.cs @@ -0,0 +1,66 @@ +using System; +using eFormAPI.Web.Infrastructure.Data; +using eFormAPI.Web.Infrastructure.Identity; +using eFormAPI.Web.Infrastructure.Security; +using Microsoft.AspNet.Identity; +using Microsoft.Owin; +using Microsoft.Owin.Security.Cookies; +using Microsoft.Owin.Security.OAuth; +using Owin; + +namespace eFormAPI.Web +{ + public partial class Startup + { + public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; } + + public static string PublicClientId { get; private set; } + + // For more information on configuring authentication, please visit https://go.microsoft.com/fwlink/?LinkId=301864 + public void ConfigureAuth(IAppBuilder app) + { + // Configure the db context and user manager to use a single instance per request + app.CreatePerOwinContext(BaseDbContext.Create); + app.CreatePerOwinContext(EformUserManager.Create); + + // Enable the application to use a cookie to store information for the signed in user + // and to use a cookie to temporarily store information about a user logging in with a third party login provider + app.UseCookieAuthentication(new CookieAuthenticationOptions()); + app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie); + + // Configure the application for OAuth based flow + PublicClientId = "self"; + OAuthOptions = new OAuthAuthorizationServerOptions + { + TokenEndpointPath = new PathString("/api/auth/token"), + Provider = new ApplicationOAuthProvider(PublicClientId), + AuthorizeEndpointPath = new PathString("/api/auth/external-login"), + AccessTokenExpireTimeSpan = TimeSpan.FromDays(14), + // In production mode set AllowInsecureHttp = false + AllowInsecureHttp = true + }; + + // Enable the application to use bearer tokens to authenticate users + app.UseOAuthBearerTokens(OAuthOptions); + + // Uncomment the following lines to enable logging in with third party login providers + //app.UseMicrosoftAccountAuthentication( + // clientId: "", + // clientSecret: ""); + + //app.UseTwitterAuthentication( + // consumerKey: "", + // consumerSecret: ""); + + //app.UseFacebookAuthentication( + // appId: "", + // appSecret: ""); + + //app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions() + //{ + // ClientId = "", + // ClientSecret = "" + //}); + } + } +} diff --git a/eFormAPI/eFormAPI/App_Start/SwaggerConfig.cs b/eFormAPI/eFormAPI/App_Start/SwaggerConfig.cs new file mode 100644 index 0000000000..9bfb9054bf --- /dev/null +++ b/eFormAPI/eFormAPI/App_Start/SwaggerConfig.cs @@ -0,0 +1,102 @@ +using System.Collections.Generic; +using System.Linq; +using System.Web.Http; +using System.Web.Http.Description; +using Swashbuckle.Application; +using Swashbuckle.Swagger; + +namespace eFormAPI.Web +{ + public class SwaggerConfig + { + public static void Register(HttpConfiguration _configuration) + { + _configuration.EnableSwagger(c => + { + c.SingleApiVersion("v1", "Eform API"); + c.IncludeXmlComments($@"{System.AppDomain.CurrentDomain.BaseDirectory}\bin\API.docs.xml"); + c.DescribeAllEnumsAsStrings(); + c.DocumentFilter(); + c.OperationFilter(); + }).EnableSwaggerUi(); + } + } + + public class AuthTokenOperation : IDocumentFilter + { + public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer) + { + swaggerDoc.paths.Add("/api/auth/token", new PathItem + { + post = new Operation + { + tags = new List { "Auth" }, + consumes = new List + { + "application/x-www-form-urlencoded" + }, + parameters = new List { + new Parameter + { + type = "string", + name = "grant_type", + required = true, + @in = "formData", + @default = "password" + }, + new Parameter + { + type = "string", + name = "username", + required = false, + @in = "formData" + }, + new Parameter + { + type = "string", + name = "password", + required = false, + @in = "formData" + } + } + } + }); + } + } + + public class AddAuthorizationHeader : IOperationFilter + { + /// + /// Adds an authorization header to the given operation in Swagger. + /// + /// The Swashbuckle operation. + /// The Swashbuckle schema registry. + /// The Swashbuckle api description. + public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription) + { + if (operation == null) return; + + if (operation.parameters == null) + { + operation.parameters = new List(); + } + + var parameter = new Parameter + { + description = "The authorization token", + @in = "header", + name = "Authorization", + required = true, + type = "string", + @default = "Bearer " + }; + + if (apiDescription.ActionDescriptor.GetCustomAttributes().Any()) + { + parameter.required = false; + } + + operation.parameters.Add(parameter); + } + } +} \ No newline at end of file diff --git a/eFormAPI/eFormAPI/App_Start/WebApiConfig.cs b/eFormAPI/eFormAPI/App_Start/WebApiConfig.cs index bbc494f8ed..bf5ce45ccf 100644 --- a/eFormAPI/eFormAPI/App_Start/WebApiConfig.cs +++ b/eFormAPI/eFormAPI/App_Start/WebApiConfig.cs @@ -3,6 +3,7 @@ using System.Net.Http.Headers; using System.Web.Http; using Autofac.Integration.WebApi; +using Microsoft.Owin.Security.OAuth; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; @@ -12,6 +13,11 @@ public static class WebApiConfig { public static void Register(HttpConfiguration config) { + // Web API configuration and services + // Configure Web API to use only bearer token authentication. + config.SuppressDefaultHostAuthentication(); + config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType)); + config.MapHttpAttributeRoutes(); var container = AutofacConfig.Container; config.DependencyResolver = new AutofacWebApiDependencyResolver(container); diff --git a/eFormAPI/eFormAPI/Areas/HelpPage/ModelDescriptions/ComplexTypeModelDescription.cs b/eFormAPI/eFormAPI/Areas/HelpPage/ModelDescriptions/ComplexTypeModelDescription.cs deleted file mode 100644 index 9b275941cf..0000000000 --- a/eFormAPI/eFormAPI/Areas/HelpPage/ModelDescriptions/ComplexTypeModelDescription.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Collections.ObjectModel; - -namespace eFormAPI.Areas.HelpPage.ModelDescriptions -{ - public class ComplexTypeModelDescription : ModelDescription - { - public ComplexTypeModelDescription() - { - Properties = new Collection(); - } - - public Collection Properties { get; private set; } - } -} \ No newline at end of file diff --git a/eFormAPI/eFormAPI/Controllers/AccountController.cs b/eFormAPI/eFormAPI/Controllers/AccountController.cs new file mode 100644 index 0000000000..2394b77dbf --- /dev/null +++ b/eFormAPI/eFormAPI/Controllers/AccountController.cs @@ -0,0 +1,472 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Security.Claims; +using System.Security.Cryptography; +using System.Web; +using System.Web.Http; +using eFormAPI.Web.Infrastructure.Identity; +using eFromAPI.Common.Models.Auth; +using Microsoft.AspNet.Identity; +using Microsoft.AspNet.Identity.Owin; +using Microsoft.Owin.Security; + +namespace eFormAPI.Web.Controllers +{ + [Authorize] + [RoutePrefix("api/account")] + public class AccountController : ApiController + { + private EformUserManager _userManager; + + public AccountController() + { + } + + public AccountController(EformUserManager userManager, + ISecureDataFormat accessTokenFormat) + { + UserManager = userManager; + AccessTokenFormat = accessTokenFormat; + } + + public EformUserManager UserManager + { + get => _userManager ?? Request.GetOwinContext().GetUserManager(); + private set => _userManager = value; + } + + public ISecureDataFormat AccessTokenFormat { get; private set; } + + // GET api/account/user-info + [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)] + [Route("user-info")] + public UserInfoViewModel GetUserInfo() + { + var externalLogin = ExternalLoginData.FromIdentity(User.Identity as ClaimsIdentity); + + return new UserInfoViewModel + { + Email = User.Identity.GetUserName(), + HasRegistered = externalLogin == null, + LoginProvider = externalLogin?.LoginProvider + }; + } + + #region Help Action + + //// GET api/Account/ManageInfo?returnUrl=%2F&generateState=true + //[Route("ManageInfo")] + //public async Task GetManageInfo(string returnUrl, bool generateState = false) + //{ + // EformUser user = await UserManager.FindByIdAsync(User.Identity.GetUserId()); + + // if (user == null) + // { + // return null; + // } + + // List logins = new List(); + + // foreach (EformUserLogin linkedAccount in user.Logins) + // { + // logins.Add(new UserLoginInfoViewModel + // { + // LoginProvider = linkedAccount.LoginProvider, + // ProviderKey = linkedAccount.ProviderKey + // }); + // } + + // if (user.PasswordHash != null) + // { + // logins.Add(new UserLoginInfoViewModel + // { + // LoginProvider = LocalLoginProvider, + // ProviderKey = user.UserName, + // }); + // } + + // return new ManageInfoViewModel + // { + // LocalLoginProvider = LocalLoginProvider, + // Email = user.UserName, + // Logins = logins, + // ExternalLoginProviders = GetExternalLogins(returnUrl, generateState) + // }; + //} + //[Route("change-password")] + //public async Task ChangePassword(ChangePasswordBindingModel model) + //{ + // if (!ModelState.IsValid) + // { + // return BadRequest(ModelState); + // } + + // IdentityResult result = await UserManager.ChangePasswordAsync(User.Identity.GetUserId(), + // model.OldPassword, + // model.NewPassword); + + // if (!result.Succeeded) + // { + // return GetErrorResult(result); + // } + + // return Ok(); + //} + + //// POST api/Account/SetPassword + //[Route("SetPassword")] + //public async Task SetPassword(SetPasswordBindingModel model) + //{ + // if (!ModelState.IsValid) + // { + // return BadRequest(ModelState); + // } + + // IdentityResult result = + // await UserManager.AddPasswordAsync(User.Identity.GetUserId(), model.NewPassword); + + // if (!result.Succeeded) + // { + // return GetErrorResult(result); + // } + + // return Ok(); + //} + + //// POST api/Account/AddExternalLogin + //[Route("AddExternalLogin")] + //public async Task AddExternalLogin(AddExternalLoginBindingModel model) + //{ + // if (!ModelState.IsValid) + // { + // return BadRequest(ModelState); + // } + + // Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie); + + // AuthenticationTicket ticket = AccessTokenFormat.Unprotect(model.ExternalAccessToken); + + // if (ticket == null || ticket.Identity == null || (ticket.Properties != null + // && ticket.Properties.ExpiresUtc.HasValue + // && ticket.Properties.ExpiresUtc.Value < + // DateTimeOffset.UtcNow)) + // { + // return BadRequest("External login failure."); + // } + + // ExternalLoginData externalData = ExternalLoginData.FromIdentity(ticket.Identity); + + // if (externalData == null) + // { + // return BadRequest("The external login is already associated with an account."); + // } + + // IdentityResult result = await UserManager.AddLoginAsync(User.Identity.GetUserId(), + // new UserLoginInfo(externalData.LoginProvider, externalData.ProviderKey)); + + // if (!result.Succeeded) + // { + // return GetErrorResult(result); + // } + + // return Ok(); + //} + + //// POST api/Account/RemoveLogin + //[Route("RemoveLogin")] + //public async Task RemoveLogin(RemoveLoginBindingModel model) + //{ + // if (!ModelState.IsValid) + // { + // return BadRequest(ModelState); + // } + + // IdentityResult result; + + // if (model.LoginProvider == LocalLoginProvider) + // { + // result = await UserManager.RemovePasswordAsync(User.Identity.GetUserId()); + // } + // else + // { + // result = await UserManager.RemoveLoginAsync(User.Identity.GetUserId(), + // new UserLoginInfo(model.LoginProvider, model.ProviderKey)); + // } + + // if (!result.Succeeded) + // { + // return GetErrorResult(result); + // } + + // return Ok(); + //} + + + //// GET api/Account/ExternalLogin + //[OverrideAuthentication] + //[HostAuthentication(DefaultAuthenticationTypes.ExternalCookie)] + //[AllowAnonymous] + //[Route("ExternalLogin", Name = "ExternalLogin")] + //public async Task GetExternalLogin(string provider, string error = null) + //{ + // if (error != null) + // { + // return Redirect(Url.Content("~/") + "#error=" + Uri.EscapeDataString(error)); + // } + + // if (!User.Identity.IsAuthenticated) + // { + // return new ChallengeResult(provider, this); + // } + + // ExternalLoginData externalLogin = ExternalLoginData.FromIdentity(User.Identity as ClaimsIdentity); + + // if (externalLogin == null) + // { + // return InternalServerError(); + // } + + // if (externalLogin.LoginProvider != provider) + // { + // Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie); + // return new ChallengeResult(provider, this); + // } + + // EformUser user = await UserManager.FindAsync(new UserLoginInfo(externalLogin.LoginProvider, + // externalLogin.ProviderKey)); + + // bool hasRegistered = user != null; + + // if (hasRegistered) + // { + // Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie); + + // ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(UserManager, + // OAuthDefaults.AuthenticationType); + // ClaimsIdentity cookieIdentity = await user.GenerateUserIdentityAsync(UserManager, + // CookieAuthenticationDefaults.AuthenticationType); + + // AuthenticationProperties properties = ApplicationOAuthProvider.CreateProperties(user.UserName); + // Authentication.SignIn(properties, oAuthIdentity, cookieIdentity); + // } + // else + // { + // IEnumerable claims = externalLogin.GetClaims(); + // ClaimsIdentity identity = new ClaimsIdentity(claims, OAuthDefaults.AuthenticationType); + // Authentication.SignIn(identity); + // } + + // return Ok(); + //} + + //// GET api/Account/ExternalLogins?returnUrl=%2F&generateState=true + //[AllowAnonymous] + //[Route("ExternalLogins")] + //public IEnumerable GetExternalLogins(string returnUrl, bool generateState = false) + //{ + // IEnumerable descriptions = Authentication.GetExternalAuthenticationTypes(); + // List logins = new List(); + + // string state; + + // if (generateState) + // { + // const int strengthInBits = 256; + // state = RandomOAuthStateGenerator.Generate(strengthInBits); + // } + // else + // { + // state = null; + // } + + // foreach (AuthenticationDescription description in descriptions) + // { + // ExternalLoginViewModel login = new ExternalLoginViewModel + // { + // Name = description.Caption, + // Url = Url.Route("ExternalLogin", new + // { + // provider = description.AuthenticationType, + // response_type = "token", + // client_id = Startup.PublicClientId, + // redirect_uri = new Uri(Request.RequestUri, returnUrl).AbsoluteUri, + // state = state + // }), + // State = state + // }; + // logins.Add(login); + // } + + // return logins; + //} + + + //// POST api/Account/Register + //[AllowAnonymous] + //[Route("Register")] + //public async Task Register(RegisterBindingModel model) + //{ + // if (!ModelState.IsValid) + // { + // return BadRequest(ModelState); + // } + + // var user = new EformUser() {UserName = model.Email, Email = model.Email}; + + // IdentityResult result = await UserManager.CreateAsync(user, model.Password); + + // if (!result.Succeeded) + // { + // return GetErrorResult(result); + // } + + // return Ok(); + //} + + //// POST api/Account/RegisterExternal + //[OverrideAuthentication] + //[HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)] + //[Route("RegisterExternal")] + //public async Task RegisterExternal(RegisterExternalBindingModel model) + //{ + // if (!ModelState.IsValid) + // { + // return BadRequest(ModelState); + // } + + // var info = await Authentication.GetExternalLoginInfoAsync(); + // if (info == null) + // { + // return InternalServerError(); + // } + + // var user = new EformUser() {UserName = model.Email, Email = model.Email}; + + // IdentityResult result = await UserManager.CreateAsync(user); + // if (!result.Succeeded) + // { + // return GetErrorResult(result); + // } + + // result = await UserManager.AddLoginAsync(user.Id, info.Login); + // if (!result.Succeeded) + // { + // return GetErrorResult(result); + // } + // return Ok(); + //} + + #endregion + + #region Helpers + + protected override void Dispose(bool disposing) + { + if (disposing && _userManager != null) + { + _userManager.Dispose(); + _userManager = null; + } + + base.Dispose(disposing); + } + + private IAuthenticationManager Authentication => Request.GetOwinContext().Authentication; + + private IHttpActionResult GetErrorResult(IdentityResult result) + { + if (result == null) + { + return InternalServerError(); + } + + if (!result.Succeeded) + { + if (result.Errors != null) + { + foreach (var error in result.Errors) + { + ModelState.AddModelError("", error); + } + } + + if (ModelState.IsValid) + { + // No ModelState errors are available to send, so just return an empty BadRequest. + return BadRequest(); + } + + return BadRequest(ModelState); + } + + return null; + } + + private class ExternalLoginData + { + public string LoginProvider { get; private set; } + public string ProviderKey { get; private set; } + private string UserName { get; set; } + + public IEnumerable GetClaims() + { + IList claims = new List + { + new Claim(ClaimTypes.NameIdentifier, ProviderKey, null, LoginProvider) + }; + if (UserName != null) + { + claims.Add(new Claim(ClaimTypes.Name, UserName, null, LoginProvider)); + } + + return claims; + } + + public static ExternalLoginData FromIdentity(ClaimsIdentity identity) + { + var providerKeyClaim = identity?.FindFirst(ClaimTypes.NameIdentifier); + + if (string.IsNullOrEmpty(providerKeyClaim?.Issuer) || string.IsNullOrEmpty(providerKeyClaim.Value)) + { + return null; + } + + if (providerKeyClaim.Issuer == ClaimsIdentity.DefaultIssuer) + { + return null; + } + + return new ExternalLoginData + { + LoginProvider = providerKeyClaim.Issuer, + ProviderKey = providerKeyClaim.Value, + UserName = identity.FindFirstValue(ClaimTypes.Name) + }; + } + } + + private static class RandomOAuthStateGenerator + { + private static readonly RandomNumberGenerator _random = new RNGCryptoServiceProvider(); + + public static string Generate(int strengthInBits) + { + const int bitsPerByte = 8; + + if (strengthInBits % bitsPerByte != 0) + { + throw new ArgumentException(@"strengthInBits must be evenly divisible by 8.", "strengthInBits"); + } + + var strengthInBytes = strengthInBits / bitsPerByte; + + var data = new byte[strengthInBytes]; + _random.GetBytes(data); + return HttpServerUtility.UrlTokenEncode(data); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/eFormAPI/eFormAPI/Controllers/AuthController.cs b/eFormAPI/eFormAPI/Controllers/AuthController.cs new file mode 100644 index 0000000000..5728f63284 --- /dev/null +++ b/eFormAPI/eFormAPI/Controllers/AuthController.cs @@ -0,0 +1,55 @@ +using System.Net.Http; +using System.Web.Http; +using eFormAPI.Web.Infrastructure.Identity; +using Microsoft.AspNet.Identity.Owin; +using Microsoft.Owin.Security; +using Microsoft.Owin.Security.Cookies; + +namespace eFormAPI.Web.Controllers +{ + [Authorize] + [RoutePrefix("api/auth")] + public class AuthController : ApiController + { + private EformUserManager _userManager; + + public AuthController() + { + } + + public AuthController(EformUserManager userManager, + ISecureDataFormat accessTokenFormat) + { + UserManager = userManager; + AccessTokenFormat = accessTokenFormat; + } + + public ISecureDataFormat AccessTokenFormat { get; private set; } + private IAuthenticationManager Authentication => Request.GetOwinContext().Authentication; + + public EformUserManager UserManager + { + get => _userManager ?? Request.GetOwinContext().GetUserManager(); + private set => _userManager = value; + } + + // POST api/Account/Logout + [Route("logout")] + public IHttpActionResult Logout() + { + Authentication.SignOut(CookieAuthenticationDefaults.AuthenticationType); + return Ok(); + } + + protected override void Dispose(bool disposing) + { + if (disposing && _userManager != null) + { + _userManager.Dispose(); + _userManager = null; + } + + base.Dispose(disposing); + } + } +} \ No newline at end of file diff --git a/eFormAPI/eFormAPI/Controllers/CasesController.cs b/eFormAPI/eFormAPI/Controllers/CasesController.cs index 178d92d6a5..32c9277d97 100644 --- a/eFormAPI/eFormAPI/Controllers/CasesController.cs +++ b/eFormAPI/eFormAPI/Controllers/CasesController.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using System.Web.Http; -using eFormAPI.Web.Helpers; +using eFormAPI.Web.Infrastructure.Helpers; using eFormShared; using eFormData; using eFromAPI.Common.API; diff --git a/eFormAPI/eFormAPI/Controllers/EntitySearchController.cs b/eFormAPI/eFormAPI/Controllers/EntitySearchController.cs index 46c73d57af..49b7db6ca3 100644 --- a/eFormAPI/eFormAPI/Controllers/EntitySearchController.cs +++ b/eFormAPI/eFormAPI/Controllers/EntitySearchController.cs @@ -1,147 +1,145 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web.Http; -using eFormAPI.Web.Helpers; -using eFormShared; -using eFormData; -using eFromAPI.Common.API; -using eFromAPI.Common.Models.SearchableList; - -namespace eFormAPI.Web.Controllers -{ - public class EntitySearchController : ApiController - { - private readonly EFormCoreHelper _coreHelper = new EFormCoreHelper(); - - [HttpPost] - [Route("api/searchable-groups")] - public OperationDataResult GetEntityGroupList(AdvEntityGroupListRequestModel requestModel) - { - try - { - var core = _coreHelper.GetCore(); - var model = core.Advanced_EntityGroupAll(requestModel.Sort, requestModel.NameFilter, requestModel.PageIndex, requestModel.PageSize, "EntitySearch", requestModel.IsSortDsc, "not_removed"); - return new OperationDataResult(true, model); - } - catch (Exception e) - { - return new OperationDataResult(false, "Searchable list loading failed"); - } - } - - [HttpPost] - [Route("api/searchable-groups/create")] - public OperationResult CreateEntityGroup(AdvEntityGroupEditModel editModel) - { - try - { - var core = _coreHelper.GetCore(); - - var groupCreate = core.EntityGroupCreate("EntitySearch", editModel.Name); - - if (editModel.AdvEntityItemModels.Any()) - { - EntityGroup entityGroup = core.EntityGroupRead(groupCreate.EntityGroupMUId); - - var nextItemUid = entityGroup.EntityGroupItemLst.Count; - - foreach (var entityItem in editModel.AdvEntityItemModels) - { - entityGroup.EntityGroupItemLst.Add(new EntityItem(entityItem.Name, - entityItem.Description, nextItemUid.ToString(), "created")); - nextItemUid++; - } - - core.EntityGroupUpdate(entityGroup); - } - - - - return new OperationResult(true, $"{groupCreate.EntityGroupMUId} created successfully"); - } - catch (Exception exception) - { - return new OperationResult(false, "Searchable list creation failed"); - } - } - - [HttpPost] - [Route("api/searchable-groups/update")] - public OperationResult UpdateEntityGroup(AdvEntityGroupEditModel editModel) - { - try - { - var core = _coreHelper.GetCore(); - - EntityGroup entityGroup = core.EntityGroupRead(editModel.GroupUid); - - entityGroup.EntityGroupItemLst = editModel.AdvEntityItemModels; - entityGroup.Name = editModel.Name; - - core.EntityGroupUpdate(entityGroup); - - return new OperationResult(true, $"{editModel.GroupUid} updated successfully"); - } - catch (Exception exception) - { - return new OperationResult(false, "Searchable list creation failed"); - } - } - - [HttpGet] - [Route("api/searchable-groups/get/{entityGroupUid}")] - public OperationDataResult GetEntityGroup(string entityGroupUid) - { - try - { - var core = _coreHelper.GetCore(); - - EntityGroup entityGroup = core.EntityGroupRead(entityGroupUid); - - return new OperationDataResult(true, entityGroup); - } - catch (Exception exception) - { - return new OperationDataResult(false, "Error when obtaining searchable list"); - } - } - - [HttpGet] - [Route("api/searchable-groups/delete/{entityGroupUid}")] - public OperationResult DeleteEntityGroup(string entityGroupUid) - { - try - { - var core = _coreHelper.GetCore(); - - - return core.EntityGroupDelete(entityGroupUid) - ? new OperationResult(true, $"{entityGroupUid} deleted successfully") - : new OperationResult(false, "Error when deleting searchable list"); - } - catch (Exception exception) - { - return new OperationResult(false, "Error when deleting searchable list"); - } - } - - - [HttpPost] - [Route("api/searchable-groups/send")] - public OperationResult SendSearchableGroup(string entityGroupUid) - { - try - { - var core = _coreHelper.GetCore(); - - - return new OperationResult(true, $"deleted successfully"); - } - catch (Exception exception) - { - return new OperationResult(false, "Error when deleting searchable list"); - } - } - } +using System; +using System.Linq; +using System.Web.Http; +using eFormAPI.Web.Infrastructure.Helpers; +using eFormData; +using eFromAPI.Common.API; +using eFromAPI.Common.Models.SearchableList; + +namespace eFormAPI.Web.Controllers +{ + public class EntitySearchController : ApiController + { + private readonly EFormCoreHelper _coreHelper = new EFormCoreHelper(); + + [HttpPost] + [Route("api/searchable-groups")] + public OperationDataResult GetEntityGroupList(AdvEntityGroupListRequestModel requestModel) + { + try + { + var core = _coreHelper.GetCore(); + var model = core.Advanced_EntityGroupAll(requestModel.Sort, requestModel.NameFilter, requestModel.PageIndex, requestModel.PageSize, "EntitySearch", requestModel.IsSortDsc, "not_removed"); + return new OperationDataResult(true, model); + } + catch (Exception e) + { + return new OperationDataResult(false, "Searchable list loading failed"); + } + } + + [HttpPost] + [Route("api/searchable-groups/create")] + public OperationResult CreateEntityGroup(AdvEntityGroupEditModel editModel) + { + try + { + var core = _coreHelper.GetCore(); + + var groupCreate = core.EntityGroupCreate("EntitySearch", editModel.Name); + + if (editModel.AdvEntityItemModels.Any()) + { + EntityGroup entityGroup = core.EntityGroupRead(groupCreate.EntityGroupMUId); + + var nextItemUid = entityGroup.EntityGroupItemLst.Count; + + foreach (var entityItem in editModel.AdvEntityItemModels) + { + entityGroup.EntityGroupItemLst.Add(new EntityItem(entityItem.Name, + entityItem.Description, nextItemUid.ToString(), "created")); + nextItemUid++; + } + + core.EntityGroupUpdate(entityGroup); + } + + + + return new OperationResult(true, $"{groupCreate.EntityGroupMUId} created successfully"); + } + catch (Exception exception) + { + return new OperationResult(false, "Searchable list creation failed"); + } + } + + [HttpPost] + [Route("api/searchable-groups/update")] + public OperationResult UpdateEntityGroup(AdvEntityGroupEditModel editModel) + { + try + { + var core = _coreHelper.GetCore(); + + EntityGroup entityGroup = core.EntityGroupRead(editModel.GroupUid); + + entityGroup.EntityGroupItemLst = editModel.AdvEntityItemModels; + entityGroup.Name = editModel.Name; + + core.EntityGroupUpdate(entityGroup); + + return new OperationResult(true, $"{editModel.GroupUid} updated successfully"); + } + catch (Exception exception) + { + return new OperationResult(false, "Searchable list creation failed"); + } + } + + [HttpGet] + [Route("api/searchable-groups/get/{entityGroupUid}")] + public OperationDataResult GetEntityGroup(string entityGroupUid) + { + try + { + var core = _coreHelper.GetCore(); + + EntityGroup entityGroup = core.EntityGroupRead(entityGroupUid); + + return new OperationDataResult(true, entityGroup); + } + catch (Exception exception) + { + return new OperationDataResult(false, "Error when obtaining searchable list"); + } + } + + [HttpGet] + [Route("api/searchable-groups/delete/{entityGroupUid}")] + public OperationResult DeleteEntityGroup(string entityGroupUid) + { + try + { + var core = _coreHelper.GetCore(); + + + return core.EntityGroupDelete(entityGroupUid) + ? new OperationResult(true, $"{entityGroupUid} deleted successfully") + : new OperationResult(false, "Error when deleting searchable list"); + } + catch (Exception exception) + { + return new OperationResult(false, "Error when deleting searchable list"); + } + } + + + [HttpPost] + [Route("api/searchable-groups/send")] + public OperationResult SendSearchableGroup(string entityGroupUid) + { + try + { + var core = _coreHelper.GetCore(); + + + return new OperationResult(true, $"deleted successfully"); + } + catch (Exception exception) + { + return new OperationResult(false, "Error when deleting searchable list"); + } + } + } } \ No newline at end of file diff --git a/eFormAPI/eFormAPI/Controllers/SettingsController.cs b/eFormAPI/eFormAPI/Controllers/SettingsController.cs index 4d1df4a46b..0201c8b810 100644 --- a/eFormAPI/eFormAPI/Controllers/SettingsController.cs +++ b/eFormAPI/eFormAPI/Controllers/SettingsController.cs @@ -1,47 +1,87 @@ -using System; -using System.Web.Http; -using eFormCore; -using eFromAPI.Common.API; -using eFromAPI.Common.Models; - -namespace eFormAPI.Web.Controllers -{ - public class SettingsController : ApiController - { - [HttpPost] - public OperationResult ConnectionString(ConnectionStringModel connectionStringModel) - { - if (!ModelState.IsValid) return new OperationResult(false, "Required fields are not filled"); - - AdminTools adminTools; - string result = "Data Source=" - + connectionStringModel.Source + ";Initial Catalog=" - + connectionStringModel.Catalogue + ";" - + connectionStringModel.Auth; - - try - { - System.IO.File.AppendAllText(System.Web.Hosting.HostingEnvironment.MapPath("~/bin/Input.txt"), - result); - } - catch (Exception) - { - return new OperationResult(false, "Could not write connection string in /bin/Input.txt"); - } - - - try - { - adminTools = new AdminTools(result); - } - catch - { - return new OperationResult(false, "Connection string is invalid"); - } - - adminTools.DbSetup(connectionStringModel.Token); - - return new OperationResult(true); - } - } +using System; +using System.Configuration; +using System.Data.Entity.Infrastructure; +using System.Data.Entity.Migrations; +using System.IO; +using System.Web.Configuration; +using System.Web.Http; +using eFormCore; +using eFromAPI.Common.API; +using eFromAPI.Common.Models.Settings; +using Configuration = eFormAPI.Web.Migrations.Configuration; + +namespace eFormAPI.Web.Controllers +{ + [AllowAnonymous] + public class SettingsController : ApiController + { + [HttpPost] + public OperationResult ConnectionString(SettingsModel settingsModel) + { + + if (!ModelState.IsValid) return new OperationResult(false, "Required fields are not filled"); + + string inputPath = System.Web.Hosting.HostingEnvironment.MapPath("~/bin/Input.txt"); + AdminTools adminTools; + string sdkConnectionString = "Data Source=" + + settingsModel.ConnectionStringSdk.Source + ";Initial Catalog=" + + settingsModel.ConnectionStringSdk.Catalogue + ";" + + settingsModel.ConnectionStringSdk.Auth; + + string mainConnectionString = "Data Source=" + + settingsModel.ConnectionStringMain.Source + ";Initial Catalog=" + + settingsModel.ConnectionStringMain.Catalogue + ";" + + settingsModel.ConnectionStringMain.Auth; + + try + { + if (!File.Exists(inputPath)) + File.Create(inputPath); + + using (StreamWriter newTask = new StreamWriter(inputPath, false)) + { + newTask.WriteLine(sdkConnectionString); + } + } + catch (Exception) + { + return new OperationResult(false, "Could not write connection string in /bin/Input.txt"); + } + + + try + { + adminTools = new AdminTools(sdkConnectionString); + } + catch + { + return new OperationResult(false, "SDK connection string is invalid"); + } + + var configuration = WebConfigurationManager.OpenWebConfiguration("~"); + var section = (ConnectionStringsSection)configuration.GetSection("connectionStrings"); + section.ConnectionStrings["eFormMainConnection"].ConnectionString = mainConnectionString; + + try + { + configuration.Save(); + + var configure = new Configuration() {TargetDatabase = new DbConnectionInfo("eFormMainConnection") + }; + + var migrator = new DbMigrator(configure); + migrator.Update(); + } + catch(Exception e) + { + return new OperationResult(false, "Main connection string is invalid"); + } + + + + adminTools.DbSetup(settingsModel.ConnectionStringSdk.Token); + + return new OperationResult(true); + } + } } \ No newline at end of file diff --git a/eFormAPI/eFormAPI/Controllers/SimpleSitesController.cs b/eFormAPI/eFormAPI/Controllers/SimpleSitesController.cs index 68498367f1..c793890da1 100644 --- a/eFormAPI/eFormAPI/Controllers/SimpleSitesController.cs +++ b/eFormAPI/eFormAPI/Controllers/SimpleSitesController.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using System.Web.Http; -using eFormAPI.Web.Helpers; +using eFormAPI.Web.Infrastructure.Helpers; using eFormCore; using eFormShared; using eFromAPI.Common.API; diff --git a/eFormAPI/eFormAPI/Controllers/SitesController.cs b/eFormAPI/eFormAPI/Controllers/SitesController.cs index 67297ea64f..be949f89d8 100644 --- a/eFormAPI/eFormAPI/Controllers/SitesController.cs +++ b/eFormAPI/eFormAPI/Controllers/SitesController.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Web.Http; using AutoMapper; -using eFormAPI.Web.Helpers; +using eFormAPI.Web.Infrastructure.Helpers; using eFormCore; using eFormShared; using eFromAPI.Common.API; diff --git a/eFormAPI/eFormAPI/Controllers/TemplatesController.cs b/eFormAPI/eFormAPI/Controllers/TemplatesController.cs index 24db2d56a6..5293dcd2c6 100644 --- a/eFormAPI/eFormAPI/Controllers/TemplatesController.cs +++ b/eFormAPI/eFormAPI/Controllers/TemplatesController.cs @@ -7,7 +7,7 @@ using System.Net.Http.Headers; using System.Web; using System.Web.Http; -using eFormAPI.Web.Helpers; +using eFormAPI.Web.Infrastructure.Helpers; using eFormCore; using eFormShared; using eFromAPI.Common.API; diff --git a/eFormAPI/eFormAPI/Controllers/UnitsController.cs b/eFormAPI/eFormAPI/Controllers/UnitsController.cs index 508f09af46..1e37e24f91 100644 --- a/eFormAPI/eFormAPI/Controllers/UnitsController.cs +++ b/eFormAPI/eFormAPI/Controllers/UnitsController.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using System.Web.Http; -using eFormAPI.Web.Helpers; +using eFormAPI.Web.Infrastructure.Helpers; using eFormShared; using eFromAPI.Common.API; diff --git a/eFormAPI/eFormAPI/Controllers/ValuesController.cs b/eFormAPI/eFormAPI/Controllers/ValuesController.cs deleted file mode 100644 index 15c7872ac8..0000000000 --- a/eFormAPI/eFormAPI/Controllers/ValuesController.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Collections.Generic; -using System.Web.Http; - -namespace eFormAPI.Web.Controllers -{ - public class ValuesController : ApiController - { - // GET api/values - public IEnumerable Get() - { - return new string[] {"value1", "value2"}; - } - - - // POST api/values - public void Post([FromBody] string value) - { - } - - // PUT api/values/5 - public void Put(int id, [FromBody] string value) - { - } - - // DELETE api/values/5 - public void Delete(int id) - { - } - } -} \ No newline at end of file diff --git a/eFormAPI/eFormAPI/Controllers/WorkersController.cs b/eFormAPI/eFormAPI/Controllers/WorkersController.cs index e172fc6f18..74973f91f1 100644 --- a/eFormAPI/eFormAPI/Controllers/WorkersController.cs +++ b/eFormAPI/eFormAPI/Controllers/WorkersController.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using System.Web.Http; -using eFormAPI.Web.Helpers; +using eFormAPI.Web.Infrastructure.Helpers; using eFormCore; using eFormShared; using eFromAPI.Common.API; diff --git a/eFormAPI/eFormAPI/Global.asax.cs b/eFormAPI/eFormAPI/Global.asax.cs index 465fdf00b1..7a1fca9767 100644 --- a/eFormAPI/eFormAPI/Global.asax.cs +++ b/eFormAPI/eFormAPI/Global.asax.cs @@ -1,4 +1,5 @@ -using System.Web.Http; +using System.Diagnostics; +using System.Web.Http; using System.Web.Mvc; namespace eFormAPI.Web @@ -11,6 +12,12 @@ protected void Application_Start() AutofacConfig.ConfigureContainer(); GlobalConfiguration.Configure(WebApiConfig.Register); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); + + // Enable swagger + if (Debugger.IsAttached) + { + SwaggerConfig.Register(GlobalConfiguration.Configuration); + } } } } \ No newline at end of file diff --git a/eFormAPI/eFormAPI/Infrastructure/Data/BaseDbContext.cs b/eFormAPI/eFormAPI/Infrastructure/Data/BaseDbContext.cs new file mode 100644 index 0000000000..deee8c4bb2 --- /dev/null +++ b/eFormAPI/eFormAPI/Infrastructure/Data/BaseDbContext.cs @@ -0,0 +1,32 @@ +using System.Data.Entity; +using eFormAPI.Web.Infrastructure.Data.Entities; +using Microsoft.AspNet.Identity.EntityFramework; + +namespace eFormAPI.Web.Infrastructure.Data +{ + public class BaseDbContext : IdentityDbContext + { + public BaseDbContext() + : base("eFormMainConnection") + { + Configuration.ProxyCreationEnabled = false; + Configuration.LazyLoadingEnabled = false; + } + + public static BaseDbContext Create() + { + return new BaseDbContext(); + } + + protected override void OnModelCreating(DbModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + modelBuilder.Entity().ToTable("Users"); + modelBuilder.Entity().ToTable("Roles"); + modelBuilder.Entity().ToTable("UserRoles"); + modelBuilder.Entity().ToTable("UserClaims"); + modelBuilder.Entity().ToTable("UserLogins"); + } + } +} \ No newline at end of file diff --git a/eFormAPI/eFormAPI/Infrastructure/Data/Entities/EformRole.cs b/eFormAPI/eFormAPI/Infrastructure/Data/Entities/EformRole.cs new file mode 100644 index 0000000000..659fbd0d85 --- /dev/null +++ b/eFormAPI/eFormAPI/Infrastructure/Data/Entities/EformRole.cs @@ -0,0 +1,16 @@ +using Microsoft.AspNet.Identity.EntityFramework; + +namespace eFormAPI.Web.Infrastructure.Data.Entities +{ + public class EformRole : IdentityRole + { + public EformRole() + { + } + + public EformRole(string name) + { + Name = name; + } + } +} \ No newline at end of file diff --git a/eFormAPI/eFormAPI/Infrastructure/Data/Entities/EformRoleStore.cs b/eFormAPI/eFormAPI/Infrastructure/Data/Entities/EformRoleStore.cs new file mode 100644 index 0000000000..93f0c850bf --- /dev/null +++ b/eFormAPI/eFormAPI/Infrastructure/Data/Entities/EformRoleStore.cs @@ -0,0 +1,12 @@ +using Microsoft.AspNet.Identity.EntityFramework; + +namespace eFormAPI.Web.Infrastructure.Data.Entities +{ + public class EformRoleStore : RoleStore + { + public EformRoleStore(BaseDbContext context) + : base(context) + { + } + } +} \ No newline at end of file diff --git a/eFormAPI/eFormAPI/Infrastructure/Data/Entities/EformUser.cs b/eFormAPI/eFormAPI/Infrastructure/Data/Entities/EformUser.cs new file mode 100644 index 0000000000..3061b10f30 --- /dev/null +++ b/eFormAPI/eFormAPI/Infrastructure/Data/Entities/EformUser.cs @@ -0,0 +1,22 @@ +using System.Security.Claims; +using System.Threading.Tasks; +using Microsoft.AspNet.Identity; +using Microsoft.AspNet.Identity.EntityFramework; + +namespace eFormAPI.Web.Infrastructure.Data.Entities +{ + public class EformUser : IdentityUser + { + public async Task GenerateUserIdentityAsync( + UserManager manager, string authenticationType) + { + // Note the authenticationType must match the one defined in + // CookieAuthenticationOptions.AuthenticationType + var userIdentity = await manager.CreateIdentityAsync( + this, authenticationType); + // Add custom user claims here + return userIdentity; + } + } +} \ No newline at end of file diff --git a/eFormAPI/eFormAPI/Infrastructure/Data/Entities/EformUserClaim.cs b/eFormAPI/eFormAPI/Infrastructure/Data/Entities/EformUserClaim.cs new file mode 100644 index 0000000000..5cb0e7d06c --- /dev/null +++ b/eFormAPI/eFormAPI/Infrastructure/Data/Entities/EformUserClaim.cs @@ -0,0 +1,8 @@ +using Microsoft.AspNet.Identity.EntityFramework; + +namespace eFormAPI.Web.Infrastructure.Data.Entities +{ + public class EformUserClaim : IdentityUserClaim + { + } +} \ No newline at end of file diff --git a/eFormAPI/eFormAPI/Infrastructure/Data/Entities/EformUserLogin.cs b/eFormAPI/eFormAPI/Infrastructure/Data/Entities/EformUserLogin.cs new file mode 100644 index 0000000000..6b792ae079 --- /dev/null +++ b/eFormAPI/eFormAPI/Infrastructure/Data/Entities/EformUserLogin.cs @@ -0,0 +1,8 @@ +using Microsoft.AspNet.Identity.EntityFramework; + +namespace eFormAPI.Web.Infrastructure.Data.Entities +{ + public class EformUserLogin : IdentityUserLogin + { + } +} \ No newline at end of file diff --git a/eFormAPI/eFormAPI/Infrastructure/Data/Entities/EformUserRole.cs b/eFormAPI/eFormAPI/Infrastructure/Data/Entities/EformUserRole.cs new file mode 100644 index 0000000000..3a60afb96b --- /dev/null +++ b/eFormAPI/eFormAPI/Infrastructure/Data/Entities/EformUserRole.cs @@ -0,0 +1,8 @@ +using Microsoft.AspNet.Identity.EntityFramework; + +namespace eFormAPI.Web.Infrastructure.Data.Entities +{ + public class EformUserRole : IdentityUserRole + { + } +} \ No newline at end of file diff --git a/eFormAPI/eFormAPI/Infrastructure/Data/Entities/EformUserStore.cs b/eFormAPI/eFormAPI/Infrastructure/Data/Entities/EformUserStore.cs new file mode 100644 index 0000000000..aa8fb4ecaf --- /dev/null +++ b/eFormAPI/eFormAPI/Infrastructure/Data/Entities/EformUserStore.cs @@ -0,0 +1,13 @@ +using Microsoft.AspNet.Identity.EntityFramework; + +namespace eFormAPI.Web.Infrastructure.Data.Entities +{ + public class EformUserStore : UserStore + { + public EformUserStore(BaseDbContext context) + : base(context) + { + } + } +} \ No newline at end of file diff --git a/eFormAPI/eFormAPI/Helpers/CaseUpdateHelper.cs b/eFormAPI/eFormAPI/Infrastructure/Helpers/CaseUpdateHelper.cs similarity index 99% rename from eFormAPI/eFormAPI/Helpers/CaseUpdateHelper.cs rename to eFormAPI/eFormAPI/Infrastructure/Helpers/CaseUpdateHelper.cs index 95e9c4e1d0..d1b68cc33a 100644 --- a/eFormAPI/eFormAPI/Helpers/CaseUpdateHelper.cs +++ b/eFormAPI/eFormAPI/Infrastructure/Helpers/CaseUpdateHelper.cs @@ -3,7 +3,7 @@ using System.Linq; using eFromAPI.Common.Models.Cases.Request; -namespace eFormAPI.Web.Helpers +namespace eFormAPI.Web.Infrastructure.Helpers { public static class CaseUpdateHelper { diff --git a/eFormAPI/eFormAPI/Helpers/EFormCoreHelper.cs b/eFormAPI/eFormAPI/Infrastructure/Helpers/EFormCoreHelper.cs similarity index 95% rename from eFormAPI/eFormAPI/Helpers/EFormCoreHelper.cs rename to eFormAPI/eFormAPI/Infrastructure/Helpers/EFormCoreHelper.cs index 9ae0317252..71dd241d34 100644 --- a/eFormAPI/eFormAPI/Helpers/EFormCoreHelper.cs +++ b/eFormAPI/eFormAPI/Infrastructure/Helpers/EFormCoreHelper.cs @@ -2,10 +2,11 @@ using System.Linq; using System.Net; using System.Web.Http; +using System.Web.WebPages; using eFormCore; using NLog; -namespace eFormAPI.Web.Helpers +namespace eFormAPI.Web.Infrastructure.Helpers { public class EFormCoreHelper { @@ -44,10 +45,15 @@ public Core GetCore() { lines = System.IO.File.ReadAllLines(System.Web.Hosting.HostingEnvironment.MapPath("~/bin/Input.txt")); + + if (lines[0].IsEmpty()) + { + throw new Exception(); + } } catch (Exception) { - throw new HttpResponseException(HttpStatusCode.Unauthorized); + throw new HttpResponseException(HttpStatusCode.Forbidden); } diff --git a/eFormAPI/eFormAPI/Infrastructure/Identity/EformRoleManager.cs b/eFormAPI/eFormAPI/Infrastructure/Identity/EformRoleManager.cs new file mode 100644 index 0000000000..14b47247f4 --- /dev/null +++ b/eFormAPI/eFormAPI/Infrastructure/Identity/EformRoleManager.cs @@ -0,0 +1,22 @@ +using eFormAPI.Web.Infrastructure.Data; +using eFormAPI.Web.Infrastructure.Data.Entities; +using Microsoft.AspNet.Identity; +using Microsoft.AspNet.Identity.EntityFramework; +using Microsoft.AspNet.Identity.Owin; +using Microsoft.Owin; + +namespace eFormAPI.Web.Infrastructure.Identity +{ + public class EformRoleManager : RoleManager + { + public EformRoleManager(IRoleStore roleStore) + : base(roleStore) {} + + public static EformRoleManager Create(IdentityFactoryOptions options, IOwinContext context) + { + var appRoleManager = new EformRoleManager(new EformRoleStore(context.Get())); + + return appRoleManager; + } + } +} \ No newline at end of file diff --git a/eFormAPI/eFormAPI/Infrastructure/Identity/EformSignInManager.cs b/eFormAPI/eFormAPI/Infrastructure/Identity/EformSignInManager.cs new file mode 100644 index 0000000000..0a3c0e6e0c --- /dev/null +++ b/eFormAPI/eFormAPI/Infrastructure/Identity/EformSignInManager.cs @@ -0,0 +1,15 @@ +using eFormAPI.Web.Infrastructure.Data.Entities; +using Microsoft.AspNet.Identity; +using Microsoft.AspNet.Identity.Owin; +using Microsoft.Owin.Security; + +namespace eFormAPI.Web.Infrastructure.Identity +{ + public class EformSignInManager : SignInManager + { + public EformSignInManager(UserManager userManager, + IAuthenticationManager authenticationManager) : base(userManager, authenticationManager) + { + } + } +} \ No newline at end of file diff --git a/eFormAPI/eFormAPI/Infrastructure/Identity/EformUserManager.cs b/eFormAPI/eFormAPI/Infrastructure/Identity/EformUserManager.cs new file mode 100644 index 0000000000..47105b1a85 --- /dev/null +++ b/eFormAPI/eFormAPI/Infrastructure/Identity/EformUserManager.cs @@ -0,0 +1,56 @@ +using System; +using eFormAPI.Web.Infrastructure.Data; +using eFormAPI.Web.Infrastructure.Data.Entities; +using eFormAPI.Web.Infrastructure.Services; +using Microsoft.AspNet.Identity; +using Microsoft.AspNet.Identity.Owin; +using Microsoft.Owin; + +namespace eFormAPI.Web.Infrastructure.Identity +{ + public class EformUserManager : UserManager + { + public EformUserManager(IUserStore store) + : base(store) + { + } + + public static EformUserManager Create(IdentityFactoryOptions options, IOwinContext context) + { + var appDbContext = context.Get(); + var appUserManager = new EformUserManager(new EformUserStore(appDbContext)); + + // Configure validation logic for usernames + appUserManager.UserValidator = new UserValidator(appUserManager) + { + AllowOnlyAlphanumericUserNames = true, + RequireUniqueEmail = true + }; + + // Configure validation logic for passwords + appUserManager.PasswordValidator = new PasswordValidator + { + RequiredLength = 6, + RequireNonLetterOrDigit = true, + RequireDigit = false, + RequireLowercase = true, + RequireUppercase = true, + }; + + appUserManager.EmailService = new EmailService(); + + var dataProtectionProvider = options.DataProtectionProvider; + if (dataProtectionProvider != null) + { + appUserManager.UserTokenProvider = + new DataProtectorTokenProvider( + dataProtectionProvider.Create("ASP.NET Identity")) + { + //Code for email confirmation and reset password life time + TokenLifespan = TimeSpan.FromHours(6) + }; + } + return appUserManager; + } + } +} \ No newline at end of file diff --git a/eFormAPI/eFormAPI/Infrastructure/Security/ApplicationOAuthProvider.cs b/eFormAPI/eFormAPI/Infrastructure/Security/ApplicationOAuthProvider.cs new file mode 100644 index 0000000000..55d09d5744 --- /dev/null +++ b/eFormAPI/eFormAPI/Infrastructure/Security/ApplicationOAuthProvider.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.Security.Claims; +using System.Threading.Tasks; +using eFormAPI.Web.Infrastructure.Data.Entities; +using eFormAPI.Web.Infrastructure.Identity; +using Microsoft.AspNet.Identity.Owin; +using Microsoft.Owin.Security; +using Microsoft.Owin.Security.Cookies; +using Microsoft.Owin.Security.OAuth; + +namespace eFormAPI.Web.Infrastructure.Security +{ + public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider + { + private readonly string _publicClientId; + + public ApplicationOAuthProvider(string publicClientId) + { + _publicClientId = publicClientId ?? throw new ArgumentNullException($"publicClientId"); + } + + public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) + { + var userManager = context.OwinContext.GetUserManager(); + + EformUser user = await userManager.FindAsync(context.UserName, context.Password); + + if (user == null) + { + context.SetError("invalid_grant", "The user name or password is incorrect."); + return; + } + + ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager, + OAuthDefaults.AuthenticationType); + ClaimsIdentity cookiesIdentity = await user.GenerateUserIdentityAsync(userManager, + CookieAuthenticationDefaults.AuthenticationType); + + AuthenticationProperties properties = CreateProperties(user.UserName); + AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties); + context.Validated(ticket); + context.Request.Context.Authentication.SignIn(cookiesIdentity); + } + + public override Task TokenEndpoint(OAuthTokenEndpointContext context) + { + foreach (KeyValuePair property in context.Properties.Dictionary) + { + context.AdditionalResponseParameters.Add(property.Key, property.Value); + } + + return Task.FromResult(null); + } + + public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context) + { + // Resource owner password credentials does not provide a client ID. + if (context.ClientId == null) + { + context.Validated(); + } + + return Task.FromResult(null); + } + + public override Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriContext context) + { + if (context.ClientId == _publicClientId) + { + Uri expectedRootUri = new Uri(context.Request.Uri, "/"); + + if (expectedRootUri.AbsoluteUri == context.RedirectUri) + { + context.Validated(); + } + } + + return Task.FromResult(null); + } + + public static AuthenticationProperties CreateProperties(string userName) + { + IDictionary data = new Dictionary + { + { "userName", userName } + }; + return new AuthenticationProperties(data); + } + } +} \ No newline at end of file diff --git a/eFormAPI/eFormAPI/Infrastructure/Security/ChallengeResult.cs b/eFormAPI/eFormAPI/Infrastructure/Security/ChallengeResult.cs new file mode 100644 index 0000000000..57d81a82d3 --- /dev/null +++ b/eFormAPI/eFormAPI/Infrastructure/Security/ChallengeResult.cs @@ -0,0 +1,29 @@ +using System.Net; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using System.Web.Http; + +namespace eFormAPI.Web.Infrastructure.Security +{ + public class ChallengeResult : IHttpActionResult + { + public ChallengeResult(string loginProvider, ApiController controller) + { + LoginProvider = loginProvider; + Request = controller.Request; + } + + public string LoginProvider { get; set; } + public HttpRequestMessage Request { get; set; } + + public Task ExecuteAsync(CancellationToken cancellationToken) + { + Request.GetOwinContext().Authentication.Challenge(LoginProvider); + + HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.Unauthorized); + response.RequestMessage = Request; + return Task.FromResult(response); + } + } +} diff --git a/eFormAPI/eFormAPI/Infrastructure/Services/EmailService.cs b/eFormAPI/eFormAPI/Infrastructure/Services/EmailService.cs new file mode 100644 index 0000000000..23a7579481 --- /dev/null +++ b/eFormAPI/eFormAPI/Infrastructure/Services/EmailService.cs @@ -0,0 +1,42 @@ +using System.Threading.Tasks; +using Microsoft.AspNet.Identity; + +namespace eFormAPI.Web.Infrastructure.Services +{ + public class EmailService : IIdentityMessageService + { + public async Task SendAsync(IdentityMessage message) + { + await configSendGridasync(message); + } + + // Use NuGet to install SendGrid (Basic C# client lib) + private async Task configSendGridasync(IdentityMessage message) + { + //var myMessage = new SendGridMessage(); + + //myMessage.AddTo(message.Destination); + //myMessage.From = new System.Net.Mail.MailAddress("taiseer@bitoftech.net", "Taiseer Joudeh"); + //myMessage.Subject = message.Subject; + //myMessage.Text = message.Body; + //myMessage.Html = message.Body; + + //var credentials = new NetworkCredential(ConfigurationManager.AppSettings["emailService:Account"], + // ConfigurationManager.AppSettings["emailService:Password"]); + + //// Create a Web transport for sending email. + //var transportWeb = new Web(credentials); + + // Send the email. + //if (transportWeb != null) + //{ + // await transportWeb.DeliverAsync(myMessage); + //} + //else + //{ + //Trace.TraceError("Failed to create Web transport."); + await Task.FromResult(0); + //} + } + } +} \ No newline at end of file diff --git a/eFormAPI/eFormAPI/Migrations/201707161835437_InitialCreate.Designer.cs b/eFormAPI/eFormAPI/Migrations/201707161835437_InitialCreate.Designer.cs new file mode 100644 index 0000000000..53874d6cc4 --- /dev/null +++ b/eFormAPI/eFormAPI/Migrations/201707161835437_InitialCreate.Designer.cs @@ -0,0 +1,29 @@ +// +namespace eFormAPI.Web.Migrations +{ + using System.CodeDom.Compiler; + using System.Data.Entity.Migrations; + using System.Data.Entity.Migrations.Infrastructure; + using System.Resources; + + [GeneratedCode("EntityFramework.Migrations", "6.1.3-40302")] + public sealed partial class InitialCreate : IMigrationMetadata + { + private readonly ResourceManager Resources = new ResourceManager(typeof(InitialCreate)); + + string IMigrationMetadata.Id + { + get { return "201707161835437_InitialCreate"; } + } + + string IMigrationMetadata.Source + { + get { return null; } + } + + string IMigrationMetadata.Target + { + get { return Resources.GetString("Target"); } + } + } +} diff --git a/eFormAPI/eFormAPI/Migrations/201707161835437_InitialCreate.cs b/eFormAPI/eFormAPI/Migrations/201707161835437_InitialCreate.cs new file mode 100644 index 0000000000..55e784bfad --- /dev/null +++ b/eFormAPI/eFormAPI/Migrations/201707161835437_InitialCreate.cs @@ -0,0 +1,102 @@ +namespace eFormAPI.Web.Migrations +{ + using System.Data.Entity.Migrations; + + public partial class InitialCreate : DbMigration + { + public override void Up() + { + CreateTable( + "dbo.Roles", + c => new + { + Id = c.Int(nullable: false, identity: true), + Name = c.String(nullable: false, maxLength: 256), + }) + .PrimaryKey(t => t.Id) + .Index(t => t.Name, unique: true, name: "RoleNameIndex"); + + CreateTable( + "dbo.UserRoles", + c => new + { + UserId = c.Int(nullable: false), + RoleId = c.Int(nullable: false), + }) + .PrimaryKey(t => new { t.UserId, t.RoleId }) + .ForeignKey("dbo.Roles", t => t.RoleId, cascadeDelete: true) + .ForeignKey("dbo.Users", t => t.UserId, cascadeDelete: true) + .Index(t => t.UserId) + .Index(t => t.RoleId); + + CreateTable( + "dbo.Users", + c => new + { + Id = c.Int(nullable: false, identity: true), + FirstName = c.String(nullable: false, maxLength: 100), + LastName = c.String(nullable: false, maxLength: 100), + Level = c.Byte(nullable: false), + JoinDate = c.DateTime(nullable: false), + Email = c.String(maxLength: 256), + EmailConfirmed = c.Boolean(nullable: false), + PasswordHash = c.String(), + SecurityStamp = c.String(), + PhoneNumber = c.String(), + PhoneNumberConfirmed = c.Boolean(nullable: false), + TwoFactorEnabled = c.Boolean(nullable: false), + LockoutEndDateUtc = c.DateTime(), + LockoutEnabled = c.Boolean(nullable: false), + AccessFailedCount = c.Int(nullable: false), + UserName = c.String(nullable: false, maxLength: 256), + }) + .PrimaryKey(t => t.Id) + .Index(t => t.UserName, unique: true, name: "UserNameIndex"); + + CreateTable( + "dbo.UserClaims", + c => new + { + Id = c.Int(nullable: false, identity: true), + UserId = c.Int(nullable: false), + ClaimType = c.String(), + ClaimValue = c.String(), + }) + .PrimaryKey(t => t.Id) + .ForeignKey("dbo.Users", t => t.UserId, cascadeDelete: true) + .Index(t => t.UserId); + + CreateTable( + "dbo.UserLogins", + c => new + { + LoginProvider = c.String(nullable: false, maxLength: 128), + ProviderKey = c.String(nullable: false, maxLength: 128), + UserId = c.Int(nullable: false), + }) + .PrimaryKey(t => new { t.LoginProvider, t.ProviderKey, t.UserId }) + .ForeignKey("dbo.Users", t => t.UserId, cascadeDelete: true) + .Index(t => t.UserId); + + } + + public override void Down() + { + DropForeignKey("dbo.UserRoles", "UserId", "dbo.Users"); + DropForeignKey("dbo.UserLogins", "UserId", "dbo.Users"); + DropForeignKey("dbo.UserClaims", "UserId", "dbo.Users"); + DropForeignKey("dbo.UserRoles", "RoleId", "dbo.Roles"); + DropIndex("dbo.UserLogins", new[] { "UserId" }); + DropIndex("dbo.UserClaims", new[] { "UserId" }); + DropIndex("dbo.Users", "UserNameIndex"); + DropIndex("dbo.UserRoles", new[] { "RoleId" }); + DropIndex("dbo.UserRoles", new[] { "UserId" }); + DropIndex("dbo.Roles", "RoleNameIndex"); + DropTable("dbo.UserLogins"); + DropTable("dbo.UserClaims"); + DropTable("dbo.Users"); + DropTable("dbo.UserRoles"); + DropTable("dbo.Roles"); + } + } +} diff --git a/eFormAPI/eFormAPI/Migrations/201707161835437_InitialCreate.resx b/eFormAPI/eFormAPI/Migrations/201707161835437_InitialCreate.resx new file mode 100644 index 0000000000..927b38c0f0 --- /dev/null +++ b/eFormAPI/eFormAPI/Migrations/201707161835437_InitialCreate.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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 + + + dbo + + \ No newline at end of file diff --git a/eFormAPI/eFormAPI/Migrations/201707190837078_InitialCreate.Designer.cs b/eFormAPI/eFormAPI/Migrations/201707190837078_InitialCreate.Designer.cs new file mode 100644 index 0000000000..530d4697a2 --- /dev/null +++ b/eFormAPI/eFormAPI/Migrations/201707190837078_InitialCreate.Designer.cs @@ -0,0 +1,29 @@ +// +namespace eFormAPI.Web.Migrations +{ + using System.CodeDom.Compiler; + using System.Data.Entity.Migrations; + using System.Data.Entity.Migrations.Infrastructure; + using System.Resources; + + [GeneratedCode("EntityFramework.Migrations", "6.1.3-40302")] + public sealed partial class InitialCreate : IMigrationMetadata + { + private readonly ResourceManager Resources = new ResourceManager(typeof(InitialCreate)); + + string IMigrationMetadata.Id + { + get { return "201707190837078_InitialCreate"; } + } + + string IMigrationMetadata.Source + { + get { return null; } + } + + string IMigrationMetadata.Target + { + get { return Resources.GetString("Target"); } + } + } +} diff --git a/eFormAPI/eFormAPI/Migrations/201707190837078_InitialCreate.cs b/eFormAPI/eFormAPI/Migrations/201707190837078_InitialCreate.cs new file mode 100644 index 0000000000..6bd0be09a6 --- /dev/null +++ b/eFormAPI/eFormAPI/Migrations/201707190837078_InitialCreate.cs @@ -0,0 +1,99 @@ +namespace eFormAPI.Web.Migrations +{ + using System; + using System.Data.Entity.Migrations; + + public partial class InitialCreate : DbMigration + { + public override void Up() + { + CreateTable( + "dbo.Roles", + c => new + { + Id = c.Int(nullable: false, identity: true), + Name = c.String(nullable: false, maxLength: 256), + }) + .PrimaryKey(t => t.Id) + .Index(t => t.Name, unique: true, name: "RoleNameIndex"); + + CreateTable( + "dbo.UserRoles", + c => new + { + UserId = c.Int(nullable: false), + RoleId = c.Int(nullable: false), + }) + .PrimaryKey(t => new { t.UserId, t.RoleId }) + .ForeignKey("dbo.Roles", t => t.RoleId, cascadeDelete: true) + .ForeignKey("dbo.Users", t => t.UserId, cascadeDelete: true) + .Index(t => t.UserId) + .Index(t => t.RoleId); + + CreateTable( + "dbo.Users", + c => new + { + Id = c.Int(nullable: false, identity: true), + Email = c.String(maxLength: 256), + EmailConfirmed = c.Boolean(nullable: false), + PasswordHash = c.String(), + SecurityStamp = c.String(), + PhoneNumber = c.String(), + PhoneNumberConfirmed = c.Boolean(nullable: false), + TwoFactorEnabled = c.Boolean(nullable: false), + LockoutEndDateUtc = c.DateTime(), + LockoutEnabled = c.Boolean(nullable: false), + AccessFailedCount = c.Int(nullable: false), + UserName = c.String(nullable: false, maxLength: 256), + }) + .PrimaryKey(t => t.Id) + .Index(t => t.UserName, unique: true, name: "UserNameIndex"); + + CreateTable( + "dbo.UserClaims", + c => new + { + Id = c.Int(nullable: false, identity: true), + UserId = c.Int(nullable: false), + ClaimType = c.String(), + ClaimValue = c.String(), + }) + .PrimaryKey(t => t.Id) + .ForeignKey("dbo.Users", t => t.UserId, cascadeDelete: true) + .Index(t => t.UserId); + + CreateTable( + "dbo.UserLogins", + c => new + { + LoginProvider = c.String(nullable: false, maxLength: 128), + ProviderKey = c.String(nullable: false, maxLength: 128), + UserId = c.Int(nullable: false), + }) + .PrimaryKey(t => new { t.LoginProvider, t.ProviderKey, t.UserId }) + .ForeignKey("dbo.Users", t => t.UserId, cascadeDelete: true) + .Index(t => t.UserId); + + } + + public override void Down() + { + DropForeignKey("dbo.UserRoles", "UserId", "dbo.Users"); + DropForeignKey("dbo.UserLogins", "UserId", "dbo.Users"); + DropForeignKey("dbo.UserClaims", "UserId", "dbo.Users"); + DropForeignKey("dbo.UserRoles", "RoleId", "dbo.Roles"); + DropIndex("dbo.UserLogins", new[] { "UserId" }); + DropIndex("dbo.UserClaims", new[] { "UserId" }); + DropIndex("dbo.Users", "UserNameIndex"); + DropIndex("dbo.UserRoles", new[] { "RoleId" }); + DropIndex("dbo.UserRoles", new[] { "UserId" }); + DropIndex("dbo.Roles", "RoleNameIndex"); + DropTable("dbo.UserLogins"); + DropTable("dbo.UserClaims"); + DropTable("dbo.Users"); + DropTable("dbo.UserRoles"); + DropTable("dbo.Roles"); + } + } +} diff --git a/eFormAPI/eFormAPI/Migrations/201707190837078_InitialCreate.resx b/eFormAPI/eFormAPI/Migrations/201707190837078_InitialCreate.resx new file mode 100644 index 0000000000..3c2d6e8cef --- /dev/null +++ b/eFormAPI/eFormAPI/Migrations/201707190837078_InitialCreate.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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 + + + dbo + + \ No newline at end of file diff --git a/eFormAPI/eFormAPI/Migrations/Configuration.cs b/eFormAPI/eFormAPI/Migrations/Configuration.cs new file mode 100644 index 0000000000..edd2e2cac0 --- /dev/null +++ b/eFormAPI/eFormAPI/Migrations/Configuration.cs @@ -0,0 +1,58 @@ +using System.Linq; +using eFormAPI.Web.Infrastructure.Data; +using eFormAPI.Web.Infrastructure.Data.Entities; +using eFormAPI.Web.Infrastructure.Identity; +using Microsoft.AspNet.Identity; +using Microsoft.AspNet.Identity.EntityFramework; + +namespace eFormAPI.Web.Migrations +{ + using System; + using System.Data.Entity.Migrations; + + internal sealed class Configuration : DbMigrationsConfiguration + { + public Configuration() + { + AutomaticMigrationsEnabled = false; + } + + protected override void Seed(BaseDbContext context) + { + // Seed roles + var roleManager = new EformRoleManager(new EformRoleStore(new BaseDbContext())); + if (!roleManager.RoleExists("admin")) + { + roleManager.Create(new EformRole("admin")); + } + if (!roleManager.RoleExists("user")) + { + roleManager.Create(new EformRole("user")); + } + // Seed admin and demo users + var manager = new EformUserManager(new EformUserStore(new BaseDbContext())); + var adminUser = new EformUser() + { + UserName = "admin", + Email = "admin@mail.com", + EmailConfirmed = true, + }; + var testUser = new EformUser() + { + UserName = "test", + Email = "test@mail.com", + EmailConfirmed = true, + }; + if (!manager.Users.Any(x => x.Email.Equals(adminUser.Email))) + { + manager.Create(adminUser, "AdminP@ssword!"); + manager.AddToRole(adminUser.Id, "admin"); + } + if (!manager.Users.Any(x => x.Email.Equals(testUser.Email))) + { + manager.Create(testUser, "TestP@ssword!"); + manager.AddToRole(testUser.Id, "user"); + } + } + } +} diff --git a/eFormAPI/eFormAPI/Startup.cs b/eFormAPI/eFormAPI/Startup.cs new file mode 100644 index 0000000000..ba30656e94 --- /dev/null +++ b/eFormAPI/eFormAPI/Startup.cs @@ -0,0 +1,134 @@ +using Microsoft.Owin; +using Owin; + +[assembly: OwinStartup(typeof(eFormAPI.Web.Startup))] + +namespace eFormAPI.Web +{ + public partial class Startup + { + public void Configuration(IAppBuilder app) + { + ConfigureAuth(app); + } + } +} + + +//using System; +//using System.Configuration; +//using System.Linq; +//using System.Net.Http.Formatting; +//using System.Net.Http.Headers; +//using System.Web.Http; +//using System.Web.Mvc; +//using Autofac.Integration.WebApi; +//using eFormAPI.Web.Infrastructure.Data; +//using eFormAPI.Web.Infrastructure.Data.Entities; +//using eFormAPI.Web.Infrastructure.Identity; +//using Microsoft.AspNet.Identity; +//using Microsoft.AspNet.Identity.Owin; +//using Microsoft.Owin; +//using Microsoft.Owin.Security.Cookies; +//using Microsoft.Owin.Security.DataHandler.Encoder; +//using Microsoft.Owin.Security.OAuth; +//using Newtonsoft.Json; +//using Newtonsoft.Json.Serialization; +//using Owin; + +//namespace eFormAPI.Web +//{ +// public class Startup +// { +// public void Configuration(IAppBuilder app) +// { +// HttpConfiguration httpConfig = new HttpConfiguration(); + +// ConfigureOAuthTokenGeneration(app); + +// ConfigureOAuthTokenConsumption(app); + +// // Web api +// ConfigureWebApi(httpConfig); +// // Cors +// app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll); + +// app.UseWebApi(httpConfig); + +// AreaRegistration.RegisterAllAreas(); +// AutofacConfig.ConfigureContainer(); +// GlobalConfiguration.Configure(WebApiConfig.Register); +// FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); +// } + +// private void ConfigureOAuthTokenGeneration(IAppBuilder app) +// { +// // Configure the db context and user manager to use a single instance per request +// app.CreatePerOwinContext(BaseDbContext.Create); +// app.CreatePerOwinContext(EformUserManager.Create); + +// OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions() +// { +// //For Dev enviroment only (on production should be AllowInsecureHttp = false) +// AllowInsecureHttp = true, +// TokenEndpointPath = new PathString("/oauth/token"), +// AccessTokenExpireTimeSpan = TimeSpan.FromDays(1), +// Provider = new CustomOAuthProvider(), +// AccessTokenFormat = new CustomJwtFormat("http://localhost:59822") +// }; + +// // OAuth 2.0 Bearer Access Token Generation +// app.UseOAuthAuthorizationServer(OAuthServerOptions); +// } + +// private void ConfigureOAuthTokenConsumption(IAppBuilder app) +// { +// var issuer = "http://localhost:5000"; +// string audienceId = ConfigurationManager.AppSettings["as:AudienceId"]; +// byte[] audienceSecret = +// TextEncodings.Base64Url.Decode(ConfigurationManager.AppSettings["as:AudienceSecret"]); + +// // Api controllers with an [Authorize] attribute will be validated with JWT +// app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions() +// { +// }); + + +// app.UseCookieAuthentication(new CookieAuthenticationOptions +// { +// AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, +// LoginPath = new PathString("/Account/Login"), +// Provider = new CookieAuthenticationProvider +// { +// OnValidateIdentity = SecurityStampValidator +// .OnValidateIdentity( +// validateInterval: TimeSpan.FromMinutes(30), +// regenerateIdentityCallback: (manager, user) => +// user.GenerateUserIdentityAsync(manager, DefaultAuthenticationTypes.ApplicationCookie), +// getUserIdCallback: (id) => (id.GetUserId())) +// } +// }); +// } + +// private void ConfigureWebApi(HttpConfiguration config) +// { +// config.MapHttpAttributeRoutes(); +// var container = AutofacConfig.Container; +// config.DependencyResolver = new AutofacWebApiDependencyResolver(container); + +// // Web API configuration and services +// var jsonFormatter = config.Formatters.OfType().First(); +// jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); +// jsonFormatter.SerializerSettings.Formatting = Formatting.Indented; + +// config.Formatters.JsonFormatter.SupportedMediaTypes +// .Add(new MediaTypeHeaderValue("text/html")); + +// config.Routes.MapHttpRoute( +// name: "DefaultApi", +// routeTemplate: "api/{controller}/{action}/{id}", +// defaults: new { id = RouteParameter.Optional } +// ); +// } +// } +//} \ No newline at end of file diff --git a/eFormAPI/eFormAPI/Web.config b/eFormAPI/eFormAPI/Web.config index 664d6f9216..85a6dc6e88 100644 --- a/eFormAPI/eFormAPI/Web.config +++ b/eFormAPI/eFormAPI/Web.config @@ -1,87 +1,115 @@ - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/eFormAPI/eFormAPI/eFormAPI.Web.csproj b/eFormAPI/eFormAPI/eFormAPI.Web.csproj index 1bcdbda7a0..15f97f024d 100644 --- a/eFormAPI/eFormAPI/eFormAPI.Web.csproj +++ b/eFormAPI/eFormAPI/eFormAPI.Web.csproj @@ -1,262 +1,348 @@ - - - - - - - Debug - AnyCPU - - - 2.0 - {54404CF9-A407-4F55-BC26-B243099E29A8} - {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} - Library - Properties - eFormAPI.Web - eFormAPI.Web - v4.6 - false - true - - - - - - - - - - true - full - false - bin\ - DEBUG;TRACE - prompt - 4 - - - true - pdbonly - true - bin\ - TRACE - prompt - 4 - - - - ..\packages\Antlr.3.5.0.2\lib\Antlr3.Runtime.dll - - - ..\packages\Autofac.3.5.0\lib\net40\Autofac.dll - - - ..\packages\Autofac.WebApi2.4.0.1\lib\net45\Autofac.Integration.WebApi.dll - - - ..\packages\AutoMapper.6.0.2\lib\net45\AutoMapper.dll - - - ..\packages\Microting.eForm.1.5.5.4\lib\AWSSDK.Core.dll - - - ..\packages\Microting.eForm.1.5.5.4\lib\AWSSDK.SQS.dll - - - ..\packages\Microting.eForm.1.5.5.4\lib\eFormCommunicator.dll - - - ..\packages\Microting.eForm.1.5.5.4\lib\eFormCore.dll - - - ..\packages\Microting.eForm.1.5.5.4\lib\eFormData.dll - - - ..\packages\Microting.eForm.1.5.5.4\lib\eFormOffice.dll - - - ..\packages\Microting.eForm.1.5.5.4\lib\eFormShared.dll - - - ..\packages\Microting.eForm.1.5.5.4\lib\eFormSqlController.dll - - - ..\packages\Microting.eForm.1.5.5.4\lib\eFormSubscriber.dll - - - ..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.dll - - - ..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.SqlServer.dll - - - ..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.3\lib\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll - - - - True - ..\packages\Microsoft.Office.Interop.Excel.15.0.4795.1000\lib\net20\Microsoft.Office.Interop.Excel.dll - True - - - ..\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll - - - ..\packages\NLog.4.4.7\lib\net45\NLog.dll - - - - - - - - - - - - - - - - - - True - ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll - - - - - ..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll - - - - - True - ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll - - - ..\packages\Microsoft.AspNet.WebApi.Core.5.2.3\lib\net45\System.Web.Http.dll - - - ..\packages\Microsoft.AspNet.WebApi.WebHost.5.2.3\lib\net45\System.Web.Http.WebHost.dll - - - True - ..\packages\Microsoft.AspNet.Mvc.5.2.3\lib\net45\System.Web.Mvc.dll - - - ..\packages\Microsoft.AspNet.Web.Optimization.1.1.3\lib\net40\System.Web.Optimization.dll - - - True - ..\packages\Microsoft.AspNet.Razor.3.2.3\lib\net45\System.Web.Razor.dll - - - True - ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.dll - - - True - ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Deployment.dll - - - True - ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll - - - ..\packages\WebGrease.1.6.0\lib\WebGrease.dll - - - - - - - - - - - - - - - - - Global.asax - - - - - - - - - - Web.config - - - Web.config - - - - - Always - - - Designer - - - - - - - - {515ee205-5349-449e-be13-f83da5b601b9} - eFromAPI.Common - - - - - - - 10.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - - - - - - - - - True - True - 50493 - / - http://localhost:5000 - False - False - - - False - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - + + + + + + + Debug + AnyCPU + + + 2.0 + {54404CF9-A407-4F55-BC26-B243099E29A8} + {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + eFormAPI.Web + eFormAPI.Web + v4.6 + false + true + + + + + + + + + + true + full + false + bin\ + DEBUG;TRACE + prompt + 4 + bin\API.docs.xml + 1591; + + + true + pdbonly + true + bin\ + TRACE + prompt + 4 + + + + ..\packages\Antlr.3.5.0.2\lib\Antlr3.Runtime.dll + + + ..\packages\Autofac.4.6.0\lib\net45\Autofac.dll + True + + + ..\packages\Autofac.WebApi2.4.0.1\lib\net45\Autofac.Integration.WebApi.dll + + + ..\packages\AutoMapper.6.1.1\lib\net45\AutoMapper.dll + True + + + ..\packages\Microting.eForm.1.5.5.4\lib\AWSSDK.Core.dll + + + ..\packages\Microting.eForm.1.5.5.4\lib\AWSSDK.SQS.dll + + + ..\packages\Microting.eForm.1.5.5.4\lib\eFormCommunicator.dll + + + ..\packages\Microting.eForm.1.5.5.4\lib\eFormCore.dll + + + ..\packages\Microting.eForm.1.5.5.4\lib\eFormData.dll + + + ..\packages\Microting.eForm.1.5.5.4\lib\eFormOffice.dll + + + ..\packages\Microting.eForm.1.5.5.4\lib\eFormShared.dll + + + ..\packages\Microting.eForm.1.5.5.4\lib\eFormSqlController.dll + + + ..\packages\Microting.eForm.1.5.5.4\lib\eFormSubscriber.dll + + + ..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.dll + + + ..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.SqlServer.dll + + + ..\packages\Microsoft.AspNet.Identity.Core.2.2.1\lib\net45\Microsoft.AspNet.Identity.Core.dll + + + ..\packages\Microsoft.AspNet.Identity.EntityFramework.2.2.1\lib\net45\Microsoft.AspNet.Identity.EntityFramework.dll + + + ..\packages\Microsoft.AspNet.Identity.Owin.2.2.1\lib\net45\Microsoft.AspNet.Identity.Owin.dll + + + ..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.5\lib\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll + + + + ..\packages\Microsoft.IdentityModel.Logging.1.1.4\lib\net451\Microsoft.IdentityModel.Logging.dll + + + ..\packages\Microsoft.IdentityModel.Tokens.5.1.4\lib\net451\Microsoft.IdentityModel.Tokens.dll + + + True + ..\packages\Microsoft.Office.Interop.Excel.15.0.4795.1000\lib\net20\Microsoft.Office.Interop.Excel.dll + True + + + ..\packages\Microsoft.Owin.3.1.0\lib\net45\Microsoft.Owin.dll + + + ..\packages\Microsoft.Owin.Cors.3.1.0\lib\net45\Microsoft.Owin.Cors.dll + + + ..\packages\Microsoft.Owin.Host.SystemWeb.3.1.0\lib\net45\Microsoft.Owin.Host.SystemWeb.dll + + + ..\packages\Microsoft.Owin.Security.3.1.0\lib\net45\Microsoft.Owin.Security.dll + + + ..\packages\Microsoft.Owin.Security.Cookies.3.1.0\lib\net45\Microsoft.Owin.Security.Cookies.dll + + + ..\packages\Microsoft.Owin.Security.OAuth.3.1.0\lib\net45\Microsoft.Owin.Security.OAuth.dll + + + ..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll + True + + + ..\packages\NLog.4.4.11\lib\net45\NLog.dll + + + ..\packages\Owin.1.0\lib\net40\Owin.dll + + + ..\packages\Swashbuckle.Core.5.6.0\lib\net40\Swashbuckle.Core.dll + + + + + + + ..\packages\System.IdentityModel.Tokens.Jwt.5.1.4\lib\net451\System.IdentityModel.Tokens.Jwt.dll + + + ..\packages\Microsoft.AspNet.Cors.5.0.0\lib\net45\System.Web.Cors.dll + + + + + + + + ..\packages\Microsoft.AspNet.WebApi.Owin.5.2.3\lib\net45\System.Web.Http.Owin.dll + + + + + + + + + + True + ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll + + + + + ..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll + + + + + True + ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll + + + ..\packages\Microsoft.AspNet.WebApi.Core.5.2.3\lib\net45\System.Web.Http.dll + + + ..\packages\Microsoft.AspNet.WebApi.WebHost.5.2.3\lib\net45\System.Web.Http.WebHost.dll + + + True + ..\packages\Microsoft.AspNet.Mvc.5.2.3\lib\net45\System.Web.Mvc.dll + + + ..\packages\Microsoft.AspNet.Web.Optimization.1.1.3\lib\net40\System.Web.Optimization.dll + + + True + ..\packages\Microsoft.AspNet.Razor.3.2.3\lib\net45\System.Web.Razor.dll + + + True + ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.dll + + + True + ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Deployment.dll + + + True + ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll + + + ..\packages\WebActivatorEx.2.0\lib\net40\WebActivatorEx.dll + + + ..\packages\WebGrease.1.6.0\lib\WebGrease.dll + + + + + + + + + + + + + + + + + + + + Global.asax + + + + + + + + + + + + + + + + + + + 201707190837078_InitialCreate.cs + + + + + + + + + + + Web.config + + + Web.config + + + + + Always + + + + + Designer + + + + + {515ee205-5349-449e-be13-f83da5b601b9} + eFromAPI.Common + + + + + Designer + + + + + 201707190837078_InitialCreate.cs + + + + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + + + + + + + + + True + True + 50493 + / + http://localhost:5000 + False + False + + + False + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + \ No newline at end of file diff --git a/eFormAPI/eFormAPI/eFormAPI.Web.csproj.user b/eFormAPI/eFormAPI/eFormAPI.Web.csproj.user index 394e1f1fa5..00a356a04f 100644 --- a/eFormAPI/eFormAPI/eFormAPI.Web.csproj.user +++ b/eFormAPI/eFormAPI/eFormAPI.Web.csproj.user @@ -1,37 +1,37 @@ - - - - true - 600 - True - False - True - - False - - - - - - - - CurrentPage - True - False - False - False - - - - - - - - - True - True - - - - + + + + true + 600 + True + False + True + + False + + + + + + + + CurrentPage + True + False + False + False + + + + + + + + + True + True + + + + \ No newline at end of file diff --git a/eFormAPI/eFormAPI/packages.config b/eFormAPI/eFormAPI/packages.config index d8c9ec904d..a1413904a1 100644 --- a/eFormAPI/eFormAPI/packages.config +++ b/eFormAPI/eFormAPI/packages.config @@ -1,31 +1,48 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/eFormAPI/eFromAPI.Common/App.config b/eFormAPI/eFromAPI.Common/App.config index eadf5338ea..7eccb98e4a 100644 --- a/eFormAPI/eFromAPI.Common/App.config +++ b/eFormAPI/eFromAPI.Common/App.config @@ -1,21 +1,21 @@ - - - - -
- - - - - - - - - - - - - - - + + + + +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/eFormAPI/eFromAPI.Common/Models/Auth/AccountBindingModels.cs b/eFormAPI/eFromAPI.Common/Models/Auth/AccountBindingModels.cs new file mode 100644 index 0000000000..1777799fca --- /dev/null +++ b/eFormAPI/eFromAPI.Common/Models/Auth/AccountBindingModels.cs @@ -0,0 +1,61 @@ +using System.ComponentModel.DataAnnotations; + +namespace eFromAPI.Common.Models.Auth +{ + public class CreateUserBindingModel + { + [Required] + [EmailAddress] + [Display(Name = "Email")] + public string Email { get; set; } + + [Required] + [Display(Name = "Username")] + public string Username { get; set; } + + [Required] + [Display(Name = "First Name")] + public string FirstName { get; set; } + + [Required] + [Display(Name = "Last Name")] + public string LastName { get; set; } + + [Display(Name = "Role Name")] + public string RoleName { get; set; } + + [Required] + [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] + [DataType(DataType.Password)] + [Display(Name = "Password")] + public string Password { get; set; } + + [Required] + [DataType(DataType.Password)] + [Display(Name = "Confirm password")] + [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] + public string ConfirmPassword { get; set; } + } + + public class ChangePasswordBindingModel + { + + [Required] + [DataType(DataType.Password)] + [Display(Name = "Current password")] + public string OldPassword { get; set; } + + [Required] + [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] + [DataType(DataType.Password)] + [Display(Name = "New password")] + public string NewPassword { get; set; } + + [Required] + [DataType(DataType.Password)] + [Display(Name = "Confirm new password")] + [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] + public string ConfirmPassword { get; set; } + + } +} \ No newline at end of file diff --git a/eFormAPI/eFromAPI.Common/Models/Auth/ClaimBindingModel.cs b/eFormAPI/eFromAPI.Common/Models/Auth/ClaimBindingModel.cs new file mode 100644 index 0000000000..cf107f1071 --- /dev/null +++ b/eFormAPI/eFromAPI.Common/Models/Auth/ClaimBindingModel.cs @@ -0,0 +1,15 @@ +using System.ComponentModel.DataAnnotations; + +namespace eFromAPI.Common.Models.Auth +{ + public class ClaimBindingModel + { + [Required] + [Display(Name = "Claim Type")] + public string Type { get; set; } + + [Required] + [Display(Name = "Claim Value")] + public string Value { get; set; } + } +} \ No newline at end of file diff --git a/eFormAPI/eFromAPI.Common/Models/Auth/RoleBindingModels.cs b/eFormAPI/eFromAPI.Common/Models/Auth/RoleBindingModels.cs new file mode 100644 index 0000000000..963fa7ba40 --- /dev/null +++ b/eFormAPI/eFromAPI.Common/Models/Auth/RoleBindingModels.cs @@ -0,0 +1,100 @@ +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; + +namespace eFromAPI.Common.Models.Auth +{ + + public class AddExternalLoginBindingModel + { + [Required] + [Display(Name = "External access token")] + public string ExternalAccessToken { get; set; } + } + + + public class RegisterBindingModel + { + [Required] + [Display(Name = "Email")] + public string Email { get; set; } + + [Required] + [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] + [DataType(DataType.Password)] + [Display(Name = "Password")] + public string Password { get; set; } + + [DataType(DataType.Password)] + [Display(Name = "Confirm password")] + [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] + public string ConfirmPassword { get; set; } + } + + public class RegisterExternalBindingModel + { + [Required] + [Display(Name = "Email")] + public string Email { get; set; } + } + + public class RemoveLoginBindingModel + { + [Required] + [Display(Name = "Login provider")] + public string LoginProvider { get; set; } + + [Required] + [Display(Name = "Provider key")] + public string ProviderKey { get; set; } + } + + public class SetPasswordBindingModel + { + [Required] + [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] + [DataType(DataType.Password)] + [Display(Name = "New password")] + public string NewPassword { get; set; } + + [DataType(DataType.Password)] + [Display(Name = "Confirm new password")] + [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] + public string ConfirmPassword { get; set; } + } + public class ExternalLoginViewModel + { + public string Name { get; set; } + + public string Url { get; set; } + + public string State { get; set; } + } + + public class ManageInfoViewModel + { + public string LocalLoginProvider { get; set; } + + public string Email { get; set; } + + public IEnumerable Logins { get; set; } + + public IEnumerable ExternalLoginProviders { get; set; } + } + + public class UserInfoViewModel + { + public string Email { get; set; } + + public bool HasRegistered { get; set; } + + public string LoginProvider { get; set; } + } + + public class UserLoginInfoViewModel + { + public string LoginProvider { get; set; } + + public string ProviderKey { get; set; } + } +} + diff --git a/eFormAPI/eFromAPI.Common/Models/ConnectionStringModel.cs b/eFormAPI/eFromAPI.Common/Models/ConnectionStringModel.cs deleted file mode 100644 index db03c801ef..0000000000 --- a/eFormAPI/eFromAPI.Common/Models/ConnectionStringModel.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace eFromAPI.Common.Models -{ - public class ConnectionStringModel - { - public string Source { get; set; } - public string Catalogue { get; set; } - public string Auth { get; set; } - public string Token { get; set; } - } -} \ No newline at end of file diff --git a/eFormAPI/eFromAPI.Common/Models/SearchableList/AdvEntityGroupEditModel.cs b/eFormAPI/eFromAPI.Common/Models/SearchableList/AdvEntityGroupEditModel.cs index 909720ff04..0b9f179abc 100644 --- a/eFormAPI/eFromAPI.Common/Models/SearchableList/AdvEntityGroupEditModel.cs +++ b/eFormAPI/eFromAPI.Common/Models/SearchableList/AdvEntityGroupEditModel.cs @@ -1,16 +1,12 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using eFormData; - -namespace eFromAPI.Common.Models.SearchableList -{ - public class AdvEntityGroupEditModel - { - public string Name { get; set; } - public string GroupUid { get; set; } - public List AdvEntityItemModels { get; set; } - } -} +using System.Collections.Generic; +using eFormData; + +namespace eFromAPI.Common.Models.SearchableList +{ + public class AdvEntityGroupEditModel + { + public string Name { get; set; } + public string GroupUid { get; set; } + public List AdvEntityItemModels { get; set; } + } +} diff --git a/eFormAPI/eFromAPI.Common/Models/SearchableList/AdvEntityGroupImportModel.cs b/eFormAPI/eFromAPI.Common/Models/SearchableList/AdvEntityGroupImportModel.cs index eba9c58f2f..193cbeb5e3 100644 --- a/eFormAPI/eFromAPI.Common/Models/SearchableList/AdvEntityGroupImportModel.cs +++ b/eFormAPI/eFromAPI.Common/Models/SearchableList/AdvEntityGroupImportModel.cs @@ -1,13 +1,7 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace eFromAPI.Common.Models.SearchableList -{ - public class AdvEntityGroupImportModel - { - public string ImportString { get; set; } - } -} +namespace eFromAPI.Common.Models.SearchableList +{ + public class AdvEntityGroupImportModel + { + public string ImportString { get; set; } + } +} diff --git a/eFormAPI/eFromAPI.Common/Models/SearchableList/AdvEntityGroupListRequestModel.cs b/eFormAPI/eFromAPI.Common/Models/SearchableList/AdvEntityGroupListRequestModel.cs index c316aefc88..3728f6e2b3 100644 --- a/eFormAPI/eFromAPI.Common/Models/SearchableList/AdvEntityGroupListRequestModel.cs +++ b/eFormAPI/eFromAPI.Common/Models/SearchableList/AdvEntityGroupListRequestModel.cs @@ -1,17 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace eFromAPI.Common.Models.SearchableList -{ - public class AdvEntityGroupListRequestModel - { - public string Sort { get; set; } - public string NameFilter { get; set; } - public int PageIndex { get; set; } - public int PageSize { get; set; } - public bool IsSortDsc { get; set; } - } -} +namespace eFromAPI.Common.Models.SearchableList +{ + public class AdvEntityGroupListRequestModel + { + public string Sort { get; set; } + public string NameFilter { get; set; } + public int PageIndex { get; set; } + public int PageSize { get; set; } + public bool IsSortDsc { get; set; } + } +} diff --git a/eFormAPI/eFromAPI.Common/Models/SearchableList/AdvEntityItemModel.cs b/eFormAPI/eFromAPI.Common/Models/SearchableList/AdvEntityItemModel.cs index 1037b3daf4..cf6eddfe9d 100644 --- a/eFormAPI/eFromAPI.Common/Models/SearchableList/AdvEntityItemModel.cs +++ b/eFormAPI/eFromAPI.Common/Models/SearchableList/AdvEntityItemModel.cs @@ -1,18 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using eFormData; - -namespace eFromAPI.Common.Models.SearchableList -{ - public class AdvEntityItemModel - { - public string Name { get; set; } - public string Description { get; set; } - public string EntityItemUId { get; set; } - public string WorkflowState { get; set; } - - } -} +namespace eFromAPI.Common.Models.SearchableList +{ + public class AdvEntityItemModel + { + public string Name { get; set; } + public string Description { get; set; } + public string EntityItemUId { get; set; } + public string WorkflowState { get; set; } + + } +} diff --git a/eFormAPI/eFromAPI.Common/Models/Settings/ConnectionStringMainModel.cs b/eFormAPI/eFromAPI.Common/Models/Settings/ConnectionStringMainModel.cs new file mode 100644 index 0000000000..ee39513325 --- /dev/null +++ b/eFormAPI/eFromAPI.Common/Models/Settings/ConnectionStringMainModel.cs @@ -0,0 +1,14 @@ +using System.ComponentModel.DataAnnotations; + +namespace eFromAPI.Common.Models.Settings +{ + public class ConnectionStringMainModel + { + [Required] + public string Source { get; set; } + [Required] + public string Catalogue { get; set; } + [Required] + public string Auth { get; set; } + } +} diff --git a/eFormAPI/eFromAPI.Common/Models/Settings/ConnectionStringSDKModel.cs b/eFormAPI/eFromAPI.Common/Models/Settings/ConnectionStringSDKModel.cs new file mode 100644 index 0000000000..303a190f0a --- /dev/null +++ b/eFormAPI/eFromAPI.Common/Models/Settings/ConnectionStringSDKModel.cs @@ -0,0 +1,16 @@ +using System.ComponentModel.DataAnnotations; + +namespace eFromAPI.Common.Models.Settings +{ + public class ConnectionStringSDKModel + { + [Required] + public string Source { get; set; } + [Required] + public string Catalogue { get; set; } + [Required] + public string Auth { get; set; } + [Required] + public string Token { get; set; } + } +} diff --git a/eFormAPI/eFromAPI.Common/Models/Settings/SettingsModel.cs b/eFormAPI/eFromAPI.Common/Models/Settings/SettingsModel.cs new file mode 100644 index 0000000000..5afee5ffdb --- /dev/null +++ b/eFormAPI/eFromAPI.Common/Models/Settings/SettingsModel.cs @@ -0,0 +1,8 @@ +namespace eFromAPI.Common.Models.Settings +{ + public class SettingsModel + { + public ConnectionStringMainModel ConnectionStringMain { get; set; } + public ConnectionStringSDKModel ConnectionStringSdk { get; set; } + } +} \ No newline at end of file diff --git a/eFormAPI/eFromAPI.Common/eFromAPI.Common.csproj b/eFormAPI/eFromAPI.Common/eFromAPI.Common.csproj index e597025046..450d8a64e7 100644 --- a/eFormAPI/eFromAPI.Common/eFromAPI.Common.csproj +++ b/eFormAPI/eFromAPI.Common/eFromAPI.Common.csproj @@ -1,114 +1,119 @@ - - - - - Debug - AnyCPU - {515EE205-5349-449E-BE13-F83DA5B601B9} - Library - Properties - eFromAPI.Common - eFromAPI.Common - v4.6 - 512 - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - ..\packages\Microting.eForm.1.5.5.4\lib\AWSSDK.Core.dll - - - ..\packages\Microting.eForm.1.5.5.4\lib\AWSSDK.SQS.dll - - - ..\packages\Microting.eForm.1.5.5.4\lib\eFormCommunicator.dll - - - ..\packages\Microting.eForm.1.5.5.4\lib\eFormCore.dll - - - ..\packages\Microting.eForm.1.5.5.4\lib\eFormData.dll - - - ..\packages\Microting.eForm.1.5.5.4\lib\eFormOffice.dll - - - ..\packages\Microting.eForm.1.5.5.4\lib\eFormShared.dll - - - ..\packages\Microting.eForm.1.5.5.4\lib\eFormSqlController.dll - - - ..\packages\Microting.eForm.1.5.5.4\lib\eFormSubscriber.dll - - - ..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.dll - - - ..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.SqlServer.dll - - - True - ..\packages\Microsoft.Office.Interop.Excel.15.0.4795.1000\lib\net20\Microsoft.Office.Interop.Excel.dll - True - - - ..\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + Debug + AnyCPU + {515EE205-5349-449E-BE13-F83DA5B601B9} + Library + Properties + eFromAPI.Common + eFromAPI.Common + v4.6 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\Microting.eForm.1.5.5.4\lib\AWSSDK.Core.dll + + + ..\packages\Microting.eForm.1.5.5.4\lib\AWSSDK.SQS.dll + + + ..\packages\Microting.eForm.1.5.5.4\lib\eFormCommunicator.dll + + + ..\packages\Microting.eForm.1.5.5.4\lib\eFormCore.dll + + + ..\packages\Microting.eForm.1.5.5.4\lib\eFormData.dll + + + ..\packages\Microting.eForm.1.5.5.4\lib\eFormOffice.dll + + + ..\packages\Microting.eForm.1.5.5.4\lib\eFormShared.dll + + + ..\packages\Microting.eForm.1.5.5.4\lib\eFormSqlController.dll + + + ..\packages\Microting.eForm.1.5.5.4\lib\eFormSubscriber.dll + + + ..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.dll + + + ..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.SqlServer.dll + + + True + ..\packages\Microsoft.Office.Interop.Excel.15.0.4795.1000\lib\net20\Microsoft.Office.Interop.Excel.dll + True + + + ..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/eFormAPI/eFromAPI.Common/packages.config b/eFormAPI/eFromAPI.Common/packages.config index a5ccb71e84..27bff64800 100644 --- a/eFormAPI/eFromAPI.Common/packages.config +++ b/eFormAPI/eFromAPI.Common/packages.config @@ -1,7 +1,7 @@ - - - - - - + + + + + + \ No newline at end of file diff --git a/eform-client/src/app/app.module.ts b/eform-client/src/app/app.module.ts index 3ba7bf02ba..ea18fe8c6f 100644 --- a/eform-client/src/app/app.module.ts +++ b/eform-client/src/app/app.module.ts @@ -1,9 +1,9 @@ -import {HelpersModule, NotifyService} from './modules/helpers/helpers.module'; +import {HelpersModule} from './modules/helpers/helpers.module'; import {AppRoutingModule} from './app.routing'; import {AdvancedModule} from 'app/modules/advanced/advanced.module'; -import {BrowserModule} from '@angular/platform-browser'; +import {CommonModule} from '@angular/common'; import {NgModule} from '@angular/core'; -import {FormsModule} from '@angular/forms'; +import {FormsModule, ReactiveFormsModule} from '@angular/forms'; import {HttpModule} from '@angular/http'; import {AppComponent} from './components/app.component'; import {HeaderComponent} from './components/header/header.component'; @@ -13,27 +13,73 @@ import {FullLayoutComponent} from './layouts/fulllayout/fulllayout.component'; import {SettingsModule} from './modules/settings/settings.module'; import {DndModule} from 'ng2-dnd'; import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; +import {AdminModule} from 'app/modules/admin/admin.module'; +import {AuthComponent} from 'app/components/auth/auth.component'; +import {SimpleLayoutComponent} from 'app/layouts/simple-layout/simple-layout.component'; +import {SimpleSitesModule} from 'app/modules/simple-sites/simple-sites.module'; +import {EFormService} from 'app/services/eform/eform.service'; +import { + AdminService, EntitySearchService, SettingsService, SitesService, UnitsService, + WorkersService +} from 'app/services'; +import {SimpleSitesService} from 'app/services/simple-sites.service'; +import {NotifyService} from 'app/services/notify.service'; +import {CasesService} from 'app/services/cases/cases.service'; +import {AuthService} from 'app/services/accounts/auth.service'; + +// import { +// AdminService, +// AuthService, +// EntitySearchService, +// SettingsService, +// SitesService, +// UnitsService, +// EFormService, +// CasesService, +// SimpleSitesService, +// WorkersService +// } from 'app/services'; + @NgModule({ declarations: [ AppComponent, + AuthComponent, HeaderComponent, FooterComponent, NavigationComponent, - FullLayoutComponent + FullLayoutComponent, + SimpleLayoutComponent ], imports: [ - BrowserModule, + ReactiveFormsModule, FormsModule, AppRoutingModule, + SimpleSitesModule, AdvancedModule, HttpModule, SettingsModule, HelpersModule, + AdminModule, BrowserAnimationsModule, + CommonModule, DndModule.forRoot() ], - providers: [NotifyService], + providers: [NotifyService, + AuthService, + SitesService, + CasesService, + AdminService, + NotifyService, + UnitsService, + SitesService, + WorkersService, + UnitsService, + SimpleSitesService, + EntitySearchService, + SettingsService, + EFormService, + ], bootstrap: [AppComponent] }) export class AppModule { diff --git a/eform-client/src/app/app.routing.ts b/eform-client/src/app/app.routing.ts index 1675fe4fd3..81eae1cca8 100644 --- a/eform-client/src/app/app.routing.ts +++ b/eform-client/src/app/app.routing.ts @@ -2,6 +2,8 @@ import {NgModule} from '@angular/core'; import {RouterModule, Routes} from '@angular/router'; // Layouts import {FullLayoutComponent} from './layouts/fulllayout/fulllayout.component'; +import {SimpleLayoutComponent} from 'app/layouts/simple-layout/simple-layout.component'; +import {AuthComponent} from 'app/components/auth/auth.component'; export const routes: Routes = [ { @@ -30,10 +32,26 @@ export const routes: Routes = [ { path: 'settings', loadChildren: './modules/settings/settings.module#SettingsModule' + }, + { + path: 'admin', + loadChildren: './modules/admin/admin.module#AdminModule' } ] }, - + { + path: 'login', + component: SimpleLayoutComponent, + data: { + title: 'Login' + }, + children: [ + { + path: '', + component: AuthComponent, + }, + ] + }, // otherwise redirect to home {path: '**', redirectTo: ''} ]; diff --git a/eform-client/src/app/components/auth/auth.component.css b/eform-client/src/app/components/auth/auth.component.css new file mode 100644 index 0000000000..95a44191ee --- /dev/null +++ b/eform-client/src/app/components/auth/auth.component.css @@ -0,0 +1,13 @@ +.wrapper-top { + margin-top: 100px; +} + +.img-wrapper { + max-height: 200px; + text-align: center; + margin: 0 auto; +} + +.panel { + border: 0; +} diff --git a/eform-client/src/app/components/auth/auth.component.html b/eform-client/src/app/components/auth/auth.component.html new file mode 100644 index 0000000000..f4343e4467 --- /dev/null +++ b/eform-client/src/app/components/auth/auth.component.html @@ -0,0 +1,28 @@ +
+
+
+
+
+ +

eForm Angular

+ +
+
+ + +
+
+
+ + +
+
+
{{error}}
+ +
+
+
+
+
+ +
diff --git a/eform-client/src/app/components/auth/auth.component.spec.ts b/eform-client/src/app/components/auth/auth.component.spec.ts new file mode 100644 index 0000000000..51f524bdad --- /dev/null +++ b/eform-client/src/app/components/auth/auth.component.spec.ts @@ -0,0 +1,25 @@ +import {async, ComponentFixture, TestBed} from '@angular/core/testing'; + +import {AuthComponent} from './auth.component'; + +describe('AuthComponent', () => { + let component: AuthComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [AuthComponent] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(AuthComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/eform-client/src/app/components/auth/auth.component.ts b/eform-client/src/app/components/auth/auth.component.ts new file mode 100644 index 0000000000..d830aa8e35 --- /dev/null +++ b/eform-client/src/app/components/auth/auth.component.ts @@ -0,0 +1,49 @@ +import { Component, OnInit } from '@angular/core'; +import { FormBuilder, AbstractControl, FormGroup, Validators } from '@angular/forms'; +import { Router } from '@angular/router'; +import {AuthResponseModel, LoginRequestModel} from 'app/models/auth'; +import {AuthService} from 'app/services/accounts/auth.service'; + + +@Component({ + selector: 'eform-auth', + templateUrl: './auth.component.html', + styleUrls: ['./auth.component.css'] +}) +export class AuthComponent implements OnInit { + form: FormGroup; + username: AbstractControl; + password: AbstractControl; + error: string; + + constructor(private router: Router, + private authService: AuthService, + private fb: FormBuilder) { } + + submitForm(): void { + this.authService.login(new LoginRequestModel(this.form.getRawValue())) + .subscribe((result: AuthResponseModel) => { + localStorage.setItem('currentAuth', JSON.stringify(result)); + this.router.navigate(['/']).then(); + }, + (error) => { + this.error = error; + }, + ); + } + + ngOnInit() { + this.form = this.fb.group({ + username: [ + '', + Validators.required, + ], + password: [ + '', + Validators.required, + ], + }); + this.username = this.form.get('username'); + this.password = this.form.get('password'); + } +} diff --git a/eform-client/src/app/components/navigation/navigation.component.html b/eform-client/src/app/components/navigation/navigation.component.html index b8684c3c00..91e29bbcbd 100644 --- a/eform-client/src/app/components/navigation/navigation.component.html +++ b/eform-client/src/app/components/navigation/navigation.component.html @@ -5,6 +5,9 @@