/// <summary> /// create a user /// </summary> /// <param name="email"></param> /// <param name="pass"></param> /// <param name="destroy">Whether or not a user should be destroyed if exists. If false and user exists no user destroy/recreation happens</param> /// <returns></returns> private async Task <MapHiveUser> CreateUserInternalAsync(string email, string pass, bool destroy) { //when creating org, need a user and if it exists, need to clean it up var user = await _db.Users.FirstOrDefaultAsync(u => u.Email == email); if (user != null && destroy) { await user.ForceDestroyAsync <MapHiveUser>(_db, user.Uuid); } if (user == null || destroy) { //recreate user user = new MapHiveUser { Email = email, IsAccountVerified = true }; //recreate user IDictionary <string, object> op = null; user.UserCreated += (sender, eventArgs) => { op = eventArgs.OperationFeedback; }; await user.CreateAsync(_db); var userManager = MapHive.Core.Identity.UserManagerUtils.GetUserManager(); var idUser = await userManager.FindByEmailAsync(email); //once user is created, need to perform an update in order to set it as valid var confirmEmailToken = await userManager.GenerateEmailConfirmationTokenAsync(idUser); await userManager.ConfirmEmailAsync(idUser, confirmEmailToken); //also apply pass! await Auth.ForceResetPasswordAsync(idUser.Id, pass); } return(user); }
/// <summary> /// Standardises user creation /// </summary> /// <param name="dbCtx"></param> /// <param name="user"></param> /// <param name="emailStuff"></param> /// <param name="redirectUrl"></param> /// <returns></returns> public static async Task <MapHiveUser> CreateUser(DbContext dbCtx, MapHiveUser user, Tuple <IEmailAccount, IEmailTemplate> emailStuff, string redirectUrl) { //Note: there are 2 options to send emails when creation a user account: //1. listen to UserCreated evt on the User object and then process email manually //2. grab the appropriate email template and email account, potentially adjust some email template tokens prior to creating a user and pass both sender account and email template to a user creation procedure //In this scenario a second approach is used //initial email template customisation: //{UserName} //{Email} //{RedirectUrl} var replacementData = new Dictionary <string, object> { { "UserName", $"{user.GetFullUserName()} ({user.Email})" }, { "Email", user.Email }, { "RedirectUrl", redirectUrl } }; emailStuff?.Item2.Prepare(replacementData); return(await user.CreateAsync(dbCtx, CustomUserAccountService.GetInstance("MapHiveMbr"), emailStuff?.Item1, emailStuff?.Item2)); }
protected virtual async Task Handle_AddUser(Dictionary <string, string> args) { var cmd = GetCallerName(); if (GetHelp(args)) { Console.WriteLine($"'{cmd}' : adds a user to the system"); Console.WriteLine($"syntax: {cmd} space separated params: "); Console.WriteLine("\t[e:email]"); Console.WriteLine("\t[p:pass]"); Console.WriteLine("\t[s:slug] user's slug"); Console.WriteLine("\t[o:{presence}] whether or not user is an org user"); Console.WriteLine(); Console.WriteLine($"example: {cmd} e:[email protected] p:test"); return; } var email = ExtractParam("e", args); var pass = ExtractParam("p", args); var slug = ExtractParam("s", args); var isOrgUser = ContainsParam("o", args); if (string.IsNullOrEmpty(email) || string.IsNullOrEmpty(pass)) { ConsoleEx.WriteErr("User name and pass cannot be empty!"); } ConsoleEx.WriteLine($"Creating user: '******' with the following pass: '******'; user is org user: {isOrgUser}; slug: {slug}", ConsoleColor.DarkYellow); //need a valid user to create a Core.Base object Server.Core.Utils.Identity.ImpersonateGhostUser(); var user = new MapHiveUser { Email = email, Slug = slug, IsOrgUser = isOrgUser }; //Note: db context uses a connection defined in app cfg. //TODO - make it somewhat dynamic! try { //destroy a previous account if any await DestroyUser <MapHiveUser>(email, new MapHiveDbContext("MapHiveMeta"), CustomUserAccountService.GetInstance("MapHiveMbr")); IDictionary <string, object> op = null; user.UserCreated += (sender, eventArgs) => { op = eventArgs.OperationFeedback; }; await user.CreateAsync(new MapHiveDbContext("MapHiveMeta"), CustomUserAccountService.GetInstance("MapHiveMbr")); //once user is created, need to perform an update in order to set it as valid user.IsAccountVerified = true; await user.UpdateAsync(new MapHiveDbContext("MapHiveMeta"), CustomUserAccountService.GetInstance("MapHiveMbr"), user.Uuid); //and also need to change the pass as the default procedure autogenerates a pass CustomUserAccountService.GetInstance("MapHiveMbr") .ChangePassword(user.Uuid, (string)op["InitialPassword"], pass); ConsoleEx.WriteOk($"User '{email}' with the following pass: '******' has been created."); Console.WriteLine(); } catch (Exception ex) { HandleException(ex); return; } }
/// <summary> /// Reads config details for a specified user characteristics - user uuid, token, etc. /// </summary> /// <param name="dbctx"></param> /// <param name="q"></param> /// <returns></returns> public static async Task <UserConfiguration> GetAsync <TDbCtx>( TDbCtx dbctx, UserConfigurationQuery q ) where TDbCtx : MapHiveDbContext, new() { if (q == null) { return(null); } var dbCtx = new TDbCtx(); //check if user is known MapHiveUser user = null; if (q.UserId.HasValue) { user = await new DataModel.MapHiveUser().ReadAsync(dbCtx, q.UserId.Value); } Token token = null; if (q.TokenId.HasValue) { token = await new DataModel.Token().ReadAsync(dbCtx, q.TokenId.Value, detached: true); } //Orgs IEnumerable <Organization> orgs = null; if (user != null) { //grab user orgs //FIXME - need to enable passing all the org assets here to - packages, apps, mods, data sources; see below for details orgs = await MapHiveUser.GetUserOrganizationsAsync(dbCtx, q.UserId.Value, (q.AppNames ?? string.Empty).Split(',')); } //Note: not likely to have both - user and token auth but in a case this is true, pull an org for token regardless the fact a user //may already have been 'served' above if (token != null) { var tokenOrg = dbCtx.Organizations.FirstOrDefault(org => org.Uuid == token.OrganizationId); if (tokenOrg != null) { var tmpOrgs = orgs?.ToList() ?? new List <Organization>(); //get an app token grants access too tokenOrg.Applications = await token.GetApplicationsAsync(dbCtx); tmpOrgs.Add(tokenOrg); orgs = tmpOrgs; } //also check if this is a master token and if the org for which to extract stuff has been provided explicitly! if (token.IsMaster && q.OrganizationId.HasValue) { //try to grab an org var explicitlyRequestedTokenOrg = await dbCtx.Organizations.FirstOrDefaultAsync(o => o.Uuid == q.OrganizationId); if (explicitlyRequestedTokenOrg != null) { var tmpOrgs = orgs?.ToList() ?? new List <Organization>(); //apps explicitlyRequestedTokenOrg.Applications = (await explicitlyRequestedTokenOrg.GetOrganizationAssetsAsync <Application>(dbCtx))?.assets.ToList(); ////mods //explicitlyRequestedTokenOrg.Modules = (await explicitlyRequestedTokenOrg.GetOrganizationAssetsAsync<Module>(dbCtx)).Item1.ToList(); ////and data sources //explicitlyRequestedTokenOrg.DataSources = (await explicitlyRequestedTokenOrg.GetOrganizationAssetsAsync<DataSource>(dbCtx)).Item1.ToList(); explicitlyRequestedTokenOrg.Owners = (await explicitlyRequestedTokenOrg.GetOwnersAsync(dbCtx)).ToList(); explicitlyRequestedTokenOrg.Admins = (await explicitlyRequestedTokenOrg.GetAdminsAsync(dbCtx)).ToList(); await explicitlyRequestedTokenOrg.ReadLicenseOptionsAsync(dbCtx); await explicitlyRequestedTokenOrg.LoadDatabasesAsync(dbCtx); tmpOrgs.Add(explicitlyRequestedTokenOrg); orgs = tmpOrgs; } } } //TODO - read asset links, packages and modules, so there is no need in re-reading them all over again! This will require some org assets related api changes //FIXME - so basically will need to improve the asset reading ;) foreach (var org in orgs ?? new Organization[0]) { //what we're interested in here are: //modules and data sources //Note: if there is an org present it should have the access to a specified app... //unless the app has not been specified... then all orgs a user is assigned to are returned. //Note: //GetUserOrganizations already reads requested apps to orgs, so there is no need to re-pull them here! //Same applies to token - when read it also reads the app //org.Applications = (await org.GetLinkedAssetsAsync<Application>(dbCtx)).ToList(); ////mods //org.Modules = (await org.GetOrganizationAssetsAsync<Module>(dbCtx)).Item1.ToList(); ////and data sources //org.DataSources = (await org.GetOrganizationAssetsAsync<DataSource>(dbCtx)).Item1.ToList(); org.Owners = (await org.GetOwnersAsync(dbCtx)).ToList(); org.Admins = (await org.GetAdminsAsync(dbCtx)).ToList(); org.Roles = (await org.GetOrgRolesAsync(dbCtx)).ToList(); await org.ReadLicenseOptionsAsync(dbCtx); await org.LoadDatabasesAsync(dbCtx); } //FIXME - same as above - make it possible to pass a list of org assets here //read user access to orgs / apps //this gathers info on user apps access for each org the user is assigned to if (user != null) { //user must be present as without one there is no app access really //Note: basically tokens grant direct access rights to apis and apis handle permissions on their own. foreach (var o in orgs ?? new Organization[0]) { foreach (var a in o.Applications) { a.OrgUserAppAccessCredentials = await o.GetUserAppAccessCredentialsAsync(dbCtx, user, a); //reset some properties to avoid circular refs when serializing; and to minimize payload too a.OrgUserAppAccessCredentials.User = null; a.OrgUserAppAccessCredentials.Application = null; a.OrgUserAppAccessCredentials.Organization = null; } } } var userCfg = new UserConfiguration { User = user, Orgs = orgs?.ToList(), Token = token }; //make sure do encrypt the dbs - this is sensitive shit after all userCfg.EncryptOrgDbs(q); return(userCfg); }
/// <summary> /// Creates a maphive user account /// </summary> /// <param name="email"></param> /// <param name="pass"></param> /// /// <param name="slug"></param> /// <returns></returns> protected async Task <MapHiveUser> CreateUserAsync(string email, string pass, string slug) { var user = new MapHiveUser { Email = email, Slug = slug }; ConsoleEx.WriteLine($"Creating user: '******' with the following pass: '******'; slug: {user.GetSlug()}", ConsoleColor.DarkYellow); if (RemoteMode) { user = await CreateUserRemoteAsync(email, pass, slug, true); } else { //need a valid user to create a Core.Base object Cartomatic.Utils.Identity.ImpersonateGhostUser(); //Note: db context uses a connection defined in app cfg. //TODO - make it somewhat dynamic! try { //destroy a previous account if any using (var dbCtx = GetMapHiveDbContext()) { await DestroyUserAsync <MapHiveUser>(email, dbCtx); IDictionary <string, object> op = null; user.UserCreated += (sender, eventArgs) => { op = eventArgs.OperationFeedback; }; await user.CreateAsync(dbCtx); //and also need to change the pass as the default procedure autogenerates a pass var userManager = MapHive.Core.Identity.UserManagerUtils.GetUserManager(); var idUser = await userManager.FindByEmailAsync(email); await userManager.ChangePasswordAsync(idUser, (string)op["InitialPassword"], pass); //once user is created, need to perform an update in order to set it as valid user.IsAccountVerified = true; await user.UpdateAsync(dbCtx, user.Uuid); } } catch (Exception ex) { HandleException(ex); return(null); } } ConsoleEx.WriteOk($"User '{email}' with the following pass: '******' has been created."); Console.WriteLine(); return(user); }