private static async Task Main() { Console.CancelKeyPress += (s, e) => { Environment.Exit(-1); }; // Keeper SDK needs a storage to save configuration // such as: last login name, device token, etc var configuration = new JsonConfigurationStorage("test.json"); var prompt = "Enter Email Address: "; if (!string.IsNullOrEmpty(configuration.LastLogin)) { Console.WriteLine($"Default Email Address: {configuration.LastLogin}"); } Console.Write(prompt); var username = Console.ReadLine(); if (string.IsNullOrEmpty(username)) { if (string.IsNullOrEmpty(configuration.LastLogin)) { Console.WriteLine("Bye."); return; } username = configuration.LastLogin; } var inReadLine = false; var authFlow = new AuthSync(configuration); authFlow.UiCallback = new AuthSyncCallback(() => { if (!inReadLine) { return; } if (authFlow.Step.State == AuthState.Connected || authFlow.Step.State == AuthState.Error) { Console.WriteLine("Press <Enter>"); } else { PrintStepHelp(authFlow.Step); PrintStepPrompt(authFlow.Step); } }, Console.WriteLine); // Login to Keeper Console.WriteLine("Logging in..."); var lastState = authFlow.Step.State; await authFlow.Login(username); while (!authFlow.IsCompleted) { if (authFlow.Step.State != lastState) { PrintStepHelp(authFlow.Step); } lastState = authFlow.Step.State; PrintStepPrompt(authFlow.Step); inReadLine = true; var cmd = ReadInput(); inReadLine = false; if (string.IsNullOrEmpty(cmd)) { continue; } try { await ProcessCommand(authFlow, cmd); } catch (KeeperAuthFailed) { Console.WriteLine("Invalid username or password"); } catch (Exception e) { Console.WriteLine(e.Message); } } if (authFlow.Step is ErrorStep es) { Console.WriteLine(es.Message); } if (!authFlow.IsAuthenticated()) { return; } var auth = authFlow; var vault = new VaultOnline(auth); Console.WriteLine("\nRetrieving records..."); await vault.SyncDown(); Console.WriteLine($"Hello {username}!"); Console.WriteLine($"Vault has {vault.RecordCount} records."); // Find record with title "Google" var search = vault.Records.FirstOrDefault(x => string.Compare(x.Title, "Google", StringComparison.InvariantCultureIgnoreCase) == 0); // Create a record if it does not exist. if (search == null) { search = new PasswordRecord { Title = "Google", Login = "******", Password = "******", Link = "https://google.com", Notes = "Stores google credentials" }; search = await vault.CreateRecord(search); } var nsd3 = vault.LoadNonSharedData <NonSharedData3>(search.Uid); nsd3.Data1 = "1"; nsd3.Data3 = "3"; await vault.StoreNonSharedData(search.Uid, nsd3); var nsd2 = vault.LoadNonSharedData <NonSharedData2>(search.Uid); nsd2.Data2 = "2"; await vault.StoreNonSharedData(search.Uid, nsd2); // Update record. search.SetCustomField("Security Token", "11111111"); search = await vault.UpdateRecord(search); // find file attachment. var attachment = search.Attachments .FirstOrDefault(x => string.Compare(x.Title, "google", StringComparison.InvariantCultureIgnoreCase) == 0); if (attachment == null) { // Upload local file "google.txt". // var uploadTask = new FileAttachmentUploadTask("google.txt") var fileContent = Encoding.UTF8.GetBytes("Google"); using (var stream = new MemoryStream(fileContent)) { var uploadTask = new AttachmentUploadTask(stream) { Title = "Google", Name = "google.txt", MimeType = "text/plain" }; await vault.UploadAttachment(search, uploadTask); await vault.UpdateRecord(search, false); } } else { // Download attachment into the stream // The stream could be a local file "google.txt" // using (var stream = File.OpenWrite("google.txt")) using (var stream = new MemoryStream()) { await vault.DownloadAttachment(search, attachment.Id, stream); } // Delete attachment. Remove it from the record search.Attachments.Remove(attachment); await vault.UpdateRecord(search, false); } // Find shared folder with name "Google". var sharedFolder = vault.SharedFolders .FirstOrDefault(x => string.Compare(x.Name, "Google", StringComparison.InvariantCultureIgnoreCase) == 0); if (sharedFolder == null) { // Create shared folder. var folder = await vault.CreateFolder("Google", null, new SharedFolderOptions { ManageRecords = true, ManageUsers = false, CanEdit = false, CanShare = false, }); vault.TryGetSharedFolder(folder.FolderUid, out sharedFolder); } // Add user to shared folder. try { await vault.PutUserToSharedFolder(sharedFolder.Uid, "*****@*****.**", UserType.User, new SharedFolderUserOptions { ManageRecords = false, ManageUsers = false, }); } catch (Exception e) { Console.WriteLine($"Add user to Shared Folder error: {e.Message}"); } // Add record to shared folder. await vault.MoveRecords(new[] { new RecordPath { RecordUid = search.Uid } }, sharedFolder.Uid, true); if (auth.AuthContext.IsEnterpriseAdmin) { // Load enterprise data. var enterprise = new EnterpriseData(auth); await enterprise.GetEnterpriseData(); // Find team with name "Google". var team = enterprise.Teams .FirstOrDefault(x => string.Compare(x.Name, "Google", StringComparison.InvariantCultureIgnoreCase) == 0); if (team == null) { // Create team. team = await enterprise.CreateTeam(new EnterpriseTeam { Name = "Google", RestrictEdit = false, RestrictSharing = true, RestrictView = false, }); } if (team != null) { // Add users to the "Google" team. await enterprise.AddUsersToTeams( new[] { "*****@*****.**", "*****@*****.**" }, new[] { team.Uid }, Console.WriteLine); } } Console.WriteLine("Press any key to quit"); Console.ReadKey(); }
private static async Task ProcessCommand(AuthSync auth, string command) { if (command == "?") { PrintStepHelp(auth.Step); return; } if (auth.Step is DeviceApprovalStep das) { if (command.StartsWith($"{ChannelCommand}=", StringComparison.InvariantCultureIgnoreCase)) { var channelText = command.Substring(ChannelCommand.Length + 1).ToLowerInvariant(); var channel = das.Channels.FirstOrDefault(x => x.ChannelText() == channelText); if (channel != default) { das.DefaultChannel = channel; } else { Console.WriteLine($"Device Approval push channel {channelText} not found."); } } else if (string.Compare(command, PushCommand, StringComparison.InvariantCultureIgnoreCase) == 0) { await das.SendPush(das.DefaultChannel); } else { await das.SendCode(das.DefaultChannel, command); } } else if (auth.Step is TwoFactorStep tfs) { if (command.StartsWith($"{ChannelCommand}=", StringComparison.InvariantCultureIgnoreCase)) { var channelText = command.Substring(ChannelCommand.Length + 1).ToLowerInvariant(); var channel = tfs.Channels.FirstOrDefault(x => x.ChannelText() == channelText); if (channel != default) { tfs.DefaultChannel = channel; } else { Console.WriteLine($"2FA channel {channelText} not found."); } } else if (command.StartsWith($"{ExpireCommand}=", StringComparison.InvariantCultureIgnoreCase)) { var expireText = command.Substring(ExpireCommand.Length + 1).ToLowerInvariant(); var duration = Expires.FirstOrDefault(x => x.ExpireText() == expireText); if (duration != default) { tfs.Duration = duration; } } else { var push = tfs.Channels .SelectMany(x => tfs.GetChannelPushActions(x) ?? Enumerable.Empty <TwoFactorPushAction>()) .FirstOrDefault(x => x.GetPushActionText() == command); if (push != default) { await tfs.SendPush(push); } else { await tfs.SendCode(tfs.DefaultChannel, command); } } } else if (auth.Step is PasswordStep ps) { await ps.VerifyPassword(command); } else if (auth.Step is SsoTokenStep sts) { if (string.Compare(command, "password", StringComparison.InvariantCultureIgnoreCase) == 0) { await sts.LoginWithPassword(); } else { await sts.SetSsoToken(command); } } else if (auth.Step is SsoDataKeyStep sdks) { if (AuthUIExtensions.TryParseDataKeyShareChannel(command, out var channel)) { await sdks.RequestDataKey(channel); } else { Console.WriteLine($"Invalid data key share channel: {command}"); } } else { Console.WriteLine($"Invalid command. Type \"?\" to list available commands."); } }