public async Task <bool> SaveAppUser(AppUser user, string newPasswordToHash = null) { bool success = true; if (!String.IsNullOrEmpty(newPasswordToHash)) { user.PasswordSalt = PasswordHashing.PasswordSaltInBase64(); user.PasswordHash = PasswordHashing.PasswordToHashBase64(newPasswordToHash, user.PasswordSalt); } try { using (var conn = new SqlConnection(_connectionString)) { await conn.OpenAsync(); string upsert = $"MERGE [AppUser] WITH (ROWLOCK) AS [T] " + $"USING (SELECT {user.Id} AS [id]) AS [S] " + $"ON [T].[id] = [S].[id] " + $"WHEN MATCHED THEN UPDATE SET [SubjectId]='{user.SubjectId}', [Username]='{user.Username}', [PasswordHash]='{user.PasswordHash}', [PasswordSalt]='{user.PasswordSalt}', [ProviderName]='{user.ProviderName}', [ProviderSubjectId]='{user.ProviderSubjectId}' " + $"WHEN NOT MATCHED THEN INSERT ([SubjectId],[Username],[PasswordHash],[PasswordSalt],[ProviderName],[ProviderSubjectId]) " + $"VALUES ('{user.SubjectId}','{user.Username}','{user.PasswordHash}','{user.PasswordSalt}','{user.ProviderName}','{user.ProviderSubjectId}'); " + $"SELECT SCOPE_IDENTITY();"; object result = null; using (var cmd = new SqlCommand(upsert, conn)) { result = await cmd.ExecuteScalarAsync(); } int newId = (result is null || result is DBNull) ? 0 : Convert.ToInt32(result); // SCOPE_IDENTITY returns a SQL numeric(38,0) type if (newId > 0) { user.Id = newId; } if (user.Id > 0 && user.Claims.Count > 0) { foreach (Claim c in user.Claims) { string insertIfNew = $"MERGE [Claim] AS [T] " + $"USING (SELECT {user.Id} AS [uid], '{c.Subject}' AS [sub], '{c.Type}' AS [type], '{c.Value}' as [val]) AS [S] " + $"ON [T].[AppUser_id]=[S].[uid] AND [T].[Subject]=[S].[sub] AND [T].[Type]=[S].[type] AND [T].[Value]=[S].[val] " + $"WHEN NOT MATCHED THEN INSERT ([AppUser_id],[Issuer],[OriginalIssuer],[Subject],[Type],[Value],[ValueType]) " + $"VALUES ('{user.Id}','{c.Issuer ?? string.Empty}','{c.OriginalIssuer ?? string.Empty}','{user.SubjectId}','{c.Type}','{c.Value}','{c.ValueType ?? string.Empty}');"; using (var cmd = new SqlCommand(insertIfNew, conn)) { await cmd.ExecuteNonQueryAsync(); } } } } } catch { success = false; } return(success); }
private async Task <long> CreateUserAsync(AppUser user, IFormCollection form) { await setAuthorizationHeaders(); //TODO: This needs to be moved to the so far nonexistent service layer string password = form["password"]; string role = form["role"]; user.Claims = new List <Claim>(); switch (role) { case ("user"): user.Claims.Add(new Claim( type: "role", value: "user")); break; case ("admin"): user.Claims.Add(new Claim( type: "role", value: "user")); user.Claims.Add(new Claim( type: "role", value: "admin")); break; default: //shouldn't get to here if there's proper validation throw new Exception("Something went wrong with the dropdown menu"); } user.Claims.Add(new Claim( type: "username", value: user.Username)); user.PasswordSalt = PasswordHashing.PasswordSaltInBase64(); user.PasswordHash = PasswordHashing.PasswordToHashBase64(password, user.PasswordSalt); // TODO: Change this id generation if it behaves unexpectedly(duplicates etc) user.SubjectId = PasswordHashing.PasswordSaltInBase64(); HttpResponseMessage response = await _client.PostAsJsonAsync(baseUrl, user); response.EnsureSuccessStatusCode(); string[] parts = response.Headers.Location.ToString().Split("/"); return(Convert.ToInt64(parts[parts.Length - 1])); }