24 changed files with 0 additions and 1250 deletions
@ -1,70 +0,0 @@
@@ -1,70 +0,0 @@
|
||||
using System; |
||||
using System.Configuration; |
||||
using System.Linq; |
||||
using System.Net.Http; |
||||
using System.Threading.Tasks; |
||||
using Bit.Function.Models; |
||||
using Microsoft.Azure.WebJobs; |
||||
using Microsoft.Azure.WebJobs.Host; |
||||
using Newtonsoft.Json; |
||||
|
||||
namespace Bit.Function |
||||
{ |
||||
public static class BlockIp |
||||
{ |
||||
[FunctionName("BlockIp")] |
||||
public static void Run( |
||||
[QueueTrigger("blockip", Connection = "")]string myQueueItem, |
||||
out string outputQueueItem, |
||||
TraceWriter log) |
||||
{ |
||||
outputQueueItem = BlockIpAsync(myQueueItem).GetAwaiter().GetResult(); |
||||
log.Info($"C# Queue trigger function processed: {myQueueItem}, outputted: {outputQueueItem}"); |
||||
} |
||||
|
||||
private static async Task<string> BlockIpAsync(string ipAddress) |
||||
{ |
||||
var ipWhitelist = ConfigurationManager.AppSettings["WhitelistedIps"]; |
||||
if(ipWhitelist != null && ipWhitelist.Split(',').Contains(ipAddress)) |
||||
{ |
||||
return null; |
||||
} |
||||
|
||||
var xAuthEmail = ConfigurationManager.AppSettings["X-Auth-Email"]; |
||||
var xAuthKey = ConfigurationManager.AppSettings["X-Auth-Key"]; |
||||
var zoneId = ConfigurationManager.AppSettings["ZoneId"]; |
||||
|
||||
using(var client = new HttpClient()) |
||||
{ |
||||
client.BaseAddress = new Uri("https://api.cloudflare.com"); |
||||
client.DefaultRequestHeaders.Accept.Clear(); |
||||
client.DefaultRequestHeaders.Add("X-Auth-Email", xAuthEmail); |
||||
client.DefaultRequestHeaders.Add("X-Auth-Key", xAuthKey); |
||||
|
||||
var response = await client.PostAsJsonAsync( |
||||
$"/client/v4/zones/{zoneId}/firewall/access_rules/rules", |
||||
new |
||||
{ |
||||
mode = "block", |
||||
configuration = new |
||||
{ |
||||
target = "ip", |
||||
value = ipAddress |
||||
}, |
||||
notes = $"Rate limit abuse on {DateTime.UtcNow.ToString()}." |
||||
}); |
||||
|
||||
var responseString = await response.Content.ReadAsStringAsync(); |
||||
var responseJson = JsonConvert.DeserializeObject<AccessRuleResponse>(responseString); |
||||
|
||||
if(!responseJson.Success) |
||||
{ |
||||
return null; |
||||
} |
||||
|
||||
// Uncomment whenever we can delay the returned message. Functions do not support that at this time. |
||||
return null; //responseJson.Result?.Id; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -1,41 +0,0 @@
@@ -1,41 +0,0 @@
|
||||
using System; |
||||
using System.Configuration; |
||||
using System.Data; |
||||
using System.Data.SqlClient; |
||||
using Microsoft.Azure.WebJobs; |
||||
using Microsoft.Azure.WebJobs.Host; |
||||
|
||||
namespace Bit.Function |
||||
{ |
||||
public static class DatabaseMaintenance |
||||
{ |
||||
[FunctionName("DatabaseMaintenance")] |
||||
public static void Run([TimerTrigger("0 0 4 * * *")]TimerInfo myTimer, TraceWriter log) |
||||
{ |
||||
var connectionString = ConfigurationManager.ConnectionStrings["Vault"].ConnectionString; |
||||
using(var connection = new SqlConnection(connectionString)) |
||||
{ |
||||
connection.Open(); |
||||
|
||||
// ref: http://bit.ly/2zFNcZo |
||||
var cmd = new SqlCommand("[dbo].[AzureSQLMaintenance]", connection) |
||||
{ |
||||
CommandType = CommandType.StoredProcedure |
||||
}; |
||||
|
||||
// Options: "all", "index", "statistics" |
||||
cmd.Parameters.Add("@operation", SqlDbType.NVarChar).Value = "all"; |
||||
// Options: "smart", "dummy" |
||||
cmd.Parameters.Add("@mode", SqlDbType.NVarChar).Value = "smart"; |
||||
// Options: 0, 1 |
||||
cmd.Parameters.Add("@LogToTable", SqlDbType.Bit).Value = 1; |
||||
|
||||
// Asynchronous BeginExecuteNonQuery for this long running sproc to avoid timeouts |
||||
var result = cmd.BeginExecuteNonQuery(); |
||||
cmd.EndExecuteNonQuery(result); |
||||
|
||||
log.Info($"Started [dbo].[AzureSQLMaintenance] at {DateTime.UtcNow}."); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -1,175 +0,0 @@
@@ -1,175 +0,0 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Configuration; |
||||
using System.Linq; |
||||
using System.Net; |
||||
using System.Net.Http; |
||||
using Microsoft.Azure.WebJobs; |
||||
using Microsoft.Azure.WebJobs.Extensions.Http; |
||||
using Microsoft.Azure.WebJobs.Host; |
||||
|
||||
namespace Bit.Function |
||||
{ |
||||
public static class Download |
||||
{ |
||||
// Desktop |
||||
const string DesktopCurrentVersion = "0.0.7"; |
||||
|
||||
const string DesktopWindowsPortableFileName = "Bitwarden-Portable-{0}.exe"; |
||||
const string DesktopWindowsWebInstallerFileName = "Bitwarden-Installer-{0}.exe"; |
||||
const string DesktopWindowsAppxFileName = "Bitwarden-{0}.appx"; |
||||
const string DesktopWindowsAppx32FileName = "Bitwarden-{0}-ia32.appx"; |
||||
const string DesktopWindowsStoreUrl = "https://www.microsoft.com/en-us/store/b/home"; |
||||
const string DesktopWindowsChocoUrl = "https://chocolatey.org/packages/bitwarden"; |
||||
|
||||
const string DesktopMacOsDmgFileName = "Bitwarden-{0}.dmg"; |
||||
const string DesktopMacOsPkgFileName = "Bitwarden-{0}.pkg"; |
||||
const string DesktopMacOsZipFileName = "bitwarden-{0}-mac.zip"; |
||||
const string DesktopMacOsStoreUrl = "https://itunes.com"; |
||||
const string DesktopMacOsCaskUrl = "https://caskroom.github.io/search"; |
||||
|
||||
const string DesktopLinuxAppImageFileName = "Bitwarden-{0}-x86_64.AppImage"; |
||||
const string DesktopLinuxDebFileName = "Bitwarden-{0}-amd64.deb"; |
||||
const string DesktopLinuxRpmFileName = "Bitwarden-{0}-x86_64.rpm"; |
||||
const string DesktopLinuxFreeBsdFileName = "Bitwarden-{0}.freebsd"; |
||||
const string DesktopLinuxSnapUrl = "https://snapcraft.io/"; |
||||
|
||||
// Browser |
||||
const string BrowserSafariFileUrl = "https://cdn.bitwarden.com/safari-extension/bitwarden-1.24.1.safariextz"; |
||||
const string BrowserSafariStoreUrl = "https://safari-extensions.apple.com"; |
||||
|
||||
[FunctionName("Download")] |
||||
public static HttpResponseMessage Run( |
||||
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "api/download")]HttpRequestMessage req, |
||||
TraceWriter log) |
||||
{ |
||||
var qs = req.GetQueryNameValuePairs(); |
||||
var app = GetQsParam(qs, "app")?.ToLowerInvariant(); |
||||
var platform = GetQsParam(qs, "platform")?.ToLowerInvariant(); |
||||
var variant = GetQsParam(qs, "variant")?.ToLowerInvariant(); |
||||
|
||||
if(string.IsNullOrWhiteSpace(app)) |
||||
{ |
||||
return req.CreateResponse(HttpStatusCode.BadRequest, "'app' parameter is required."); |
||||
} |
||||
|
||||
if(string.IsNullOrWhiteSpace(platform)) |
||||
{ |
||||
return req.CreateResponse(HttpStatusCode.BadRequest, "'platform' parameter is required."); |
||||
} |
||||
|
||||
if(app == "desktop") |
||||
{ |
||||
if(platform == "windows") |
||||
{ |
||||
if(variant == null || variant == "exe" || variant == "web") |
||||
{ |
||||
return GetDesktopDownloadResponse(req, DesktopWindowsWebInstallerFileName); |
||||
} |
||||
else if(variant == "portable") |
||||
{ |
||||
return GetDesktopDownloadResponse(req, DesktopWindowsPortableFileName); |
||||
} |
||||
else if(variant == "appx") |
||||
{ |
||||
return GetDesktopDownloadResponse(req, DesktopWindowsAppxFileName); |
||||
} |
||||
else if(variant == "appx32") |
||||
{ |
||||
return GetDesktopDownloadResponse(req, DesktopWindowsAppx32FileName); |
||||
} |
||||
else if(variant == "store") |
||||
{ |
||||
return GetRedirectResponse(req, DesktopWindowsStoreUrl); |
||||
} |
||||
else if(variant == "choco") |
||||
{ |
||||
return GetRedirectResponse(req, DesktopWindowsChocoUrl); |
||||
} |
||||
} |
||||
else if(platform == "mac" || platform == "macos") |
||||
{ |
||||
if(variant == null || variant == "dmg") |
||||
{ |
||||
return GetDesktopDownloadResponse(req, DesktopMacOsDmgFileName); |
||||
} |
||||
else if(variant == "pkg") |
||||
{ |
||||
return GetDesktopDownloadResponse(req, DesktopMacOsPkgFileName); |
||||
} |
||||
else if(variant == "zip") |
||||
{ |
||||
return GetDesktopDownloadResponse(req, DesktopMacOsZipFileName); |
||||
} |
||||
else if(variant == "store") |
||||
{ |
||||
return GetRedirectResponse(req, DesktopMacOsStoreUrl); |
||||
} |
||||
else if(variant == "cask" || variant == "brew") |
||||
{ |
||||
return GetRedirectResponse(req, DesktopMacOsCaskUrl); |
||||
} |
||||
} |
||||
else if(platform == "linux") |
||||
{ |
||||
if(variant == null || variant == "appimage") |
||||
{ |
||||
return GetDesktopDownloadResponse(req, DesktopLinuxAppImageFileName); |
||||
} |
||||
else if(variant == "deb") |
||||
{ |
||||
return GetDesktopDownloadResponse(req, DesktopLinuxDebFileName); |
||||
} |
||||
else if(variant == "rpm") |
||||
{ |
||||
return GetDesktopDownloadResponse(req, DesktopLinuxRpmFileName); |
||||
} |
||||
else if(variant == "freebsd") |
||||
{ |
||||
return GetDesktopDownloadResponse(req, DesktopLinuxFreeBsdFileName); |
||||
} |
||||
else if(variant == "snap") |
||||
{ |
||||
return GetRedirectResponse(req, DesktopLinuxSnapUrl); |
||||
} |
||||
} |
||||
} |
||||
else if(app == "browser") |
||||
{ |
||||
if(platform == "safari") |
||||
{ |
||||
if(variant == null || variant == "safariextz") |
||||
{ |
||||
return GetRedirectResponse(req, BrowserSafariFileUrl); |
||||
} |
||||
else if(variant == "store") |
||||
{ |
||||
return GetRedirectResponse(req, BrowserSafariStoreUrl); |
||||
} |
||||
} |
||||
} |
||||
|
||||
return req.CreateResponse(HttpStatusCode.NotFound, "Download not found."); |
||||
} |
||||
|
||||
private static string GetQsParam(IEnumerable<KeyValuePair<string, string>> qs, string key) |
||||
{ |
||||
return qs.FirstOrDefault(q => string.Compare(q.Key, key, true) == 0).Value; |
||||
} |
||||
|
||||
private static HttpResponseMessage GetDesktopDownloadResponse(HttpRequestMessage req, string filename) |
||||
{ |
||||
var filenameWithVersion = string.Format(filename, DesktopCurrentVersion); |
||||
var downloadUrl = string.Format("https://github.com/bitwarden/desktop/releases/download/v{0}/{1}", |
||||
DesktopCurrentVersion, filenameWithVersion); |
||||
return GetRedirectResponse(req, downloadUrl); |
||||
} |
||||
|
||||
private static HttpResponseMessage GetRedirectResponse(HttpRequestMessage req, string url) |
||||
{ |
||||
var response = req.CreateResponse(HttpStatusCode.Redirect); |
||||
response.Headers.Location = new Uri(url); |
||||
return response; |
||||
} |
||||
} |
||||
} |
||||
@ -1,23 +0,0 @@
@@ -1,23 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk"> |
||||
<PropertyGroup> |
||||
<TargetFramework>net471</TargetFramework> |
||||
<RootNamespace>Bit.Function</RootNamespace> |
||||
</PropertyGroup> |
||||
<ItemGroup> |
||||
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="1.0.14" /> |
||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" /> |
||||
</ItemGroup> |
||||
<ItemGroup> |
||||
<Reference Include="Microsoft.CSharp" /> |
||||
<Reference Include="System.Configuration" /> |
||||
</ItemGroup> |
||||
<ItemGroup> |
||||
<None Update="host.json"> |
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> |
||||
</None> |
||||
<None Update="local.settings.json"> |
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> |
||||
<CopyToPublishDirectory>Never</CopyToPublishDirectory> |
||||
</None> |
||||
</ItemGroup> |
||||
</Project> |
||||
@ -1,15 +0,0 @@
@@ -1,15 +0,0 @@
|
||||
using System; |
||||
using Microsoft.Azure.WebJobs; |
||||
using Microsoft.Azure.WebJobs.Host; |
||||
|
||||
namespace Bit.Function |
||||
{ |
||||
public static class KeepAlive |
||||
{ |
||||
[FunctionName("KeepAlive")] |
||||
public static void Run([TimerTrigger("0 */15 * * * *")]TimerInfo myTimer, TraceWriter log) |
||||
{ |
||||
log.Info($"C# Timer trigger function executed at: {DateTime.Now}"); |
||||
} |
||||
} |
||||
} |
||||
@ -1,8 +0,0 @@
@@ -1,8 +0,0 @@
|
||||
namespace Bit.Function.Models |
||||
{ |
||||
public class AccessRuleResponse |
||||
{ |
||||
public bool Success { get; set; } |
||||
public AccessRuleResultResponse Result { get; set; } |
||||
} |
||||
} |
||||
@ -1,15 +0,0 @@
@@ -1,15 +0,0 @@
|
||||
namespace Bit.Function.Models |
||||
{ |
||||
public class AccessRuleResultResponse |
||||
{ |
||||
public string Id { get; set; } |
||||
public string Notes { get; set; } |
||||
public ConfigurationResponse Configuration { get; set; } |
||||
|
||||
public class ConfigurationResponse |
||||
{ |
||||
public string Target { get; set; } |
||||
public string Value { get; set; } |
||||
} |
||||
} |
||||
} |
||||
@ -1,10 +0,0 @@
@@ -1,10 +0,0 @@
|
||||
using System.Collections.Generic; |
||||
|
||||
namespace Bit.Function.Models |
||||
{ |
||||
public class ListResult |
||||
{ |
||||
public bool Success { get; set; } |
||||
public List<AccessRuleResultResponse> Result { get; set; } |
||||
} |
||||
} |
||||
@ -1,132 +0,0 @@
@@ -1,132 +0,0 @@
|
||||
using System; |
||||
using System.Configuration; |
||||
using System.Net; |
||||
using System.Net.Http; |
||||
using System.Net.Mail; |
||||
using System.Text; |
||||
using System.Threading.Tasks; |
||||
using Microsoft.Azure.WebJobs; |
||||
using Microsoft.Azure.WebJobs.Extensions.Http; |
||||
using Microsoft.Azure.WebJobs.Host; |
||||
|
||||
namespace Bit.Function |
||||
{ |
||||
public static class NewHelpdeskTicket |
||||
{ |
||||
[FunctionName("NewHelpdeskTicket")] |
||||
public static HttpResponseMessage Run( |
||||
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "api/newhelpdeskticket")]HttpRequestMessage req, |
||||
TraceWriter log) |
||||
{ |
||||
//ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | |
||||
// SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; |
||||
|
||||
var data = req.Content.ReadAsFormDataAsync().Result; |
||||
if(data == null) |
||||
{ |
||||
return req.CreateResponse(HttpStatusCode.BadRequest, "No data provided."); |
||||
} |
||||
|
||||
if(string.IsNullOrWhiteSpace(data["name"])) |
||||
{ |
||||
return req.CreateResponse(HttpStatusCode.BadRequest, "Name is required."); |
||||
} |
||||
|
||||
if(data["name"].Length > 50) |
||||
{ |
||||
return req.CreateResponse(HttpStatusCode.BadRequest, "Name must be less than 50 characters."); |
||||
} |
||||
|
||||
if(string.IsNullOrWhiteSpace(data["email"])) |
||||
{ |
||||
return req.CreateResponse(HttpStatusCode.BadRequest, "Email is required."); |
||||
} |
||||
|
||||
if(data["email"].Length > 50) |
||||
{ |
||||
return req.CreateResponse(HttpStatusCode.BadRequest, "Email must be less than 50 characters."); |
||||
} |
||||
|
||||
if(!data["email"].Contains("@") || !data["email"].Contains(".")) |
||||
{ |
||||
return req.CreateResponse(HttpStatusCode.BadRequest, "Email is not valid."); |
||||
} |
||||
|
||||
if(string.IsNullOrWhiteSpace(data["message"])) |
||||
{ |
||||
return req.CreateResponse(HttpStatusCode.BadRequest, "Message is required."); |
||||
} |
||||
|
||||
//if(!await SubmitApiAsync(data["name"], data["email"], data["message"], log)) |
||||
//{ |
||||
// return req.CreateResponse(HttpStatusCode.BadRequest, "Ticket failed to create."); |
||||
//} |
||||
|
||||
SubmitEmail(data["name"], data["email"], data["message"], log); |
||||
|
||||
return req.CreateResponse(HttpStatusCode.OK, "Ticket created."); |
||||
} |
||||
|
||||
private async static Task<bool> SubmitApiAsync(string name, string email, string message, TraceWriter log) |
||||
{ |
||||
using(var client = new HttpClient()) |
||||
{ |
||||
client.BaseAddress = new Uri("https://bitwarden.freshdesk.com/api/v2"); |
||||
client.DefaultRequestHeaders.Accept.Clear(); |
||||
client.DefaultRequestHeaders.Add("Authorization", MakeFreshdeskApiAuthHeader(log)); |
||||
|
||||
var response = await client.PostAsJsonAsync("tickets", |
||||
new |
||||
{ |
||||
name = name, |
||||
email = email, |
||||
status = 2, |
||||
priority = 2, |
||||
source = 1, |
||||
subject = "Bitwarden.com Website Contact", |
||||
description = FormatMessage(message) |
||||
}); |
||||
|
||||
return response.IsSuccessStatusCode; |
||||
} |
||||
} |
||||
|
||||
private static void SubmitEmail(string name, string email, string message, TraceWriter log) |
||||
{ |
||||
var sendgridApiKey = ConfigurationManager.AppSettings["SendgridApiKey"]; |
||||
var client = new SmtpClient("smtp.sendgrid.net", /*465*/ 587) |
||||
{ |
||||
//EnableSsl = true, |
||||
Credentials = new NetworkCredential("apikey", sendgridApiKey) |
||||
}; |
||||
|
||||
var fromAddress = new MailAddress(email, name, Encoding.UTF8); |
||||
var mailMessage = new MailMessage(fromAddress, new MailAddress("bitwardencomsupport@bitwarden.freshdesk.com")) |
||||
{ |
||||
Subject = "Bitwarden.com Website Contact", |
||||
Body = FormatMessage(message), |
||||
IsBodyHtml = true |
||||
}; |
||||
|
||||
client.SendCompleted += (s, e) => |
||||
{ |
||||
client.Dispose(); |
||||
mailMessage.Dispose(); |
||||
}; |
||||
client.SendAsync(mailMessage, null); |
||||
} |
||||
|
||||
private static string FormatMessage(string message) |
||||
{ |
||||
return message.Replace("\r\n", "\n").Replace("\r", "\n").Replace("\n", "<br>"); |
||||
} |
||||
|
||||
private static string MakeFreshdeskApiAuthHeader(TraceWriter log) |
||||
{ |
||||
var freshdeskApiKey = ConfigurationManager.AppSettings["FreshdeskApiKey"]; |
||||
var b64Creds = Convert.ToBase64String( |
||||
Encoding.GetEncoding("ISO-8859-1").GetBytes(freshdeskApiKey + ":X")); |
||||
return b64Creds; |
||||
} |
||||
} |
||||
} |
||||
@ -1,88 +0,0 @@
@@ -1,88 +0,0 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Configuration; |
||||
using System.Net.Http; |
||||
using System.Threading.Tasks; |
||||
using Bit.Function.Models; |
||||
using Microsoft.Azure.WebJobs; |
||||
using Microsoft.Azure.WebJobs.Host; |
||||
using Newtonsoft.Json; |
||||
|
||||
namespace Bit.Function |
||||
{ |
||||
public static class UnblockIp |
||||
{ |
||||
[FunctionName("UnblockIp")] |
||||
public static void Run( |
||||
[QueueTrigger("unblockip", Connection = "")]string myQueueItem, |
||||
TraceWriter log) |
||||
{ |
||||
log.Info($"C# Queue trigger function processed: {myQueueItem}"); |
||||
UnblockIpAsync(myQueueItem, log).Wait(); |
||||
} |
||||
|
||||
private static async Task UnblockIpAsync(string id, TraceWriter log) |
||||
{ |
||||
if(id == null) |
||||
{ |
||||
return; |
||||
} |
||||
|
||||
var zoneId = ConfigurationManager.AppSettings["ZoneId"]; |
||||
var xAuthEmail = ConfigurationManager.AppSettings["X-Auth-Email"]; |
||||
var xAuthKey = ConfigurationManager.AppSettings["X-Auth-Key"]; |
||||
|
||||
if(id.Contains(".") || id.Contains(":")) |
||||
{ |
||||
// IP address messages. |
||||
using(var client = new HttpClient()) |
||||
{ |
||||
client.BaseAddress = new Uri("https://api.cloudflare.com"); |
||||
client.DefaultRequestHeaders.Accept.Clear(); |
||||
client.DefaultRequestHeaders.Add("X-Auth-Email", xAuthEmail); |
||||
client.DefaultRequestHeaders.Add("X-Auth-Key", xAuthKey); |
||||
|
||||
var response = await client.GetAsync($"/client/v4/zones/{zoneId}/firewall/access_rules/rules?" + |
||||
$"configuration_target=ip&configuration_value={id}"); |
||||
|
||||
var responseString = await response.Content.ReadAsStringAsync(); |
||||
var responseJson = JsonConvert.DeserializeObject<ListResult>(responseString); |
||||
|
||||
if(!responseJson.Success) |
||||
{ |
||||
return; |
||||
} |
||||
|
||||
foreach(var rule in responseJson.Result) |
||||
{ |
||||
if(rule.Configuration?.Value != id) |
||||
{ |
||||
continue; |
||||
} |
||||
|
||||
log.Info($"Unblock IP {id}, {rule.Id}"); |
||||
await DeleteRuleAsync(zoneId, xAuthEmail, xAuthKey, rule.Id); |
||||
} |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
log.Info($"Unblock Id {id}"); |
||||
await DeleteRuleAsync(zoneId, xAuthEmail, xAuthKey, id); |
||||
} |
||||
} |
||||
|
||||
private static async Task DeleteRuleAsync(string zoneId, string xAuthEmail, string xAuthKey, string id) |
||||
{ |
||||
var path = $"/client/v4/zones/{zoneId}/firewall/access_rules/rules/{id}"; |
||||
using(var client = new HttpClient()) |
||||
{ |
||||
client.BaseAddress = new Uri("https://api.cloudflare.com"); |
||||
client.DefaultRequestHeaders.Accept.Clear(); |
||||
client.DefaultRequestHeaders.Add("X-Auth-Email", xAuthEmail); |
||||
client.DefaultRequestHeaders.Add("X-Auth-Key", xAuthKey); |
||||
await client.DeleteAsync(path); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -1,7 +0,0 @@
@@ -1,7 +0,0 @@
|
||||
{ |
||||
"IsEncrypted": false, |
||||
"Values": { |
||||
"AzureWebJobsStorage": "SECRET", |
||||
"AzureWebJobsDashboard": "SECRET" |
||||
} |
||||
} |
||||
@ -1,18 +0,0 @@
@@ -1,18 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web"> |
||||
|
||||
<PropertyGroup> |
||||
<TargetFramework>netcoreapp2.1</TargetFramework> |
||||
<RootNamespace>Bit.Mail</RootNamespace> |
||||
</PropertyGroup> |
||||
|
||||
<ItemGroup> |
||||
<None Update="wwwroot\**\*"> |
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory> |
||||
</None> |
||||
</ItemGroup> |
||||
|
||||
<ItemGroup> |
||||
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.2" /> |
||||
</ItemGroup> |
||||
|
||||
</Project> |
||||
@ -1,17 +0,0 @@
@@ -1,17 +0,0 @@
|
||||
using Microsoft.AspNetCore; |
||||
using Microsoft.AspNetCore.Hosting; |
||||
|
||||
namespace Bit.Mail |
||||
{ |
||||
public class Program |
||||
{ |
||||
public static void Main(string[] args) |
||||
{ |
||||
WebHost |
||||
.CreateDefaultBuilder(args) |
||||
.UseStartup<Startup>() |
||||
.Build() |
||||
.Run(); |
||||
} |
||||
} |
||||
} |
||||
@ -1,27 +0,0 @@
@@ -1,27 +0,0 @@
|
||||
{ |
||||
"iisSettings": { |
||||
"windowsAuthentication": false, |
||||
"anonymousAuthentication": true, |
||||
"iisExpress": { |
||||
"applicationUrl": "http://localhost:33104/", |
||||
"sslPort": 0 |
||||
} |
||||
}, |
||||
"profiles": { |
||||
"IIS Express": { |
||||
"commandName": "IISExpress", |
||||
"launchBrowser": true, |
||||
"environmentVariables": { |
||||
"ASPNETCORE_ENVIRONMENT": "Development" |
||||
} |
||||
}, |
||||
"Mail": { |
||||
"commandName": "Project", |
||||
"launchBrowser": true, |
||||
"launchUrl": "http://localhost:5004", |
||||
"environmentVariables": { |
||||
"ASPNETCORE_ENVIRONMENT": "Development" |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -1,15 +0,0 @@
@@ -1,15 +0,0 @@
|
||||
using Microsoft.AspNetCore.Builder; |
||||
using Microsoft.Extensions.DependencyInjection; |
||||
|
||||
namespace Bit.Mail |
||||
{ |
||||
public class Startup |
||||
{ |
||||
public void ConfigureServices(IServiceCollection services) { } |
||||
|
||||
public void Configure(IApplicationBuilder app) |
||||
{ |
||||
app.UseFileServer(); |
||||
} |
||||
} |
||||
} |
||||
@ -1,20 +0,0 @@
@@ -1,20 +0,0 @@
|
||||
/// <binding BeforeBuild='build, dist' Clean='clean' ProjectOpened='build. dist' />
|
||||
|
||||
var gulp = require('gulp'), |
||||
rimraf = require('rimraf'), |
||||
premailer = require('gulp-premailer'); |
||||
|
||||
var paths = { |
||||
dist: '../../mail_dist/', |
||||
wwwroot: './wwwroot/' |
||||
}; |
||||
|
||||
gulp.task('inline', ['clean'], function () { |
||||
return gulp.src(paths.wwwroot + 'templates/*.html') |
||||
.pipe(premailer()) |
||||
.pipe(gulp.dest(paths.dist)); |
||||
}); |
||||
|
||||
gulp.task('clean', function (cb) { |
||||
return rimraf(paths.dist, cb); |
||||
}); |
||||
@ -1,9 +0,0 @@
@@ -1,9 +0,0 @@
|
||||
{ |
||||
"name": "bitwarden", |
||||
"version": "0.0.0", |
||||
"devDependencies": { |
||||
"gulp": "3.9.1", |
||||
"rimraf": "2.5.4", |
||||
"gulp-premailer": "0.4.0" |
||||
} |
||||
} |
||||
@ -1,18 +0,0 @@
@@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<configuration> |
||||
<!-- |
||||
Configure your application settings in appsettings.json. Learn more at http://go.microsoft.com/fwlink/?LinkId=786380 |
||||
--> |
||||
<system.webServer> |
||||
<handlers> |
||||
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" /> |
||||
</handlers> |
||||
<aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false" startupTimeLimit="3600" requestTimeout="23:00:00" /> |
||||
</system.webServer> |
||||
<appSettings> |
||||
<add key="vs:EnableBrowserLink" value="true" /> |
||||
</appSettings> |
||||
<system.web> |
||||
<compilation debug="true"></compilation> |
||||
</system.web> |
||||
</configuration> |
||||
@ -1,13 +0,0 @@
@@ -1,13 +0,0 @@
|
||||
<!DOCTYPE html> |
||||
<html> |
||||
<head> |
||||
<meta charset="utf-8" /> |
||||
<title>Bitwarden Mail Templates</title> |
||||
</head> |
||||
<body> |
||||
<ol> |
||||
<li><a href="templates/welcome.html">Welcome</a></li> |
||||
<li><a href="templates/announcement.html">Announcement</a></li> |
||||
</ol> |
||||
</body> |
||||
</html> |
||||
@ -1,282 +0,0 @@
@@ -1,282 +0,0 @@
|
||||
/* ------------------------------------- |
||||
GLOBAL |
||||
A very basic CSS reset |
||||
------------------------------------- */ |
||||
body, html, body * { |
||||
margin: 0; |
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; |
||||
box-sizing: border-box; |
||||
font-size: 16px; |
||||
color: #333; |
||||
line-height: 25px; |
||||
-webkit-font-smoothing: antialiased; |
||||
-webkit-text-size-adjust: none; |
||||
} |
||||
|
||||
img { |
||||
max-width: 100%; |
||||
border: none; |
||||
} |
||||
|
||||
body { |
||||
-webkit-font-smoothing: antialiased; |
||||
-webkit-text-size-adjust: none; |
||||
width: 100% !important; |
||||
height: 100%; |
||||
line-height: 25px; |
||||
} |
||||
|
||||
/* Let's make sure all tables have defaults */ |
||||
table td { |
||||
vertical-align: top; |
||||
} |
||||
|
||||
table td.middle { |
||||
vertical-align: middle; |
||||
} |
||||
|
||||
/* ------------------------------------- |
||||
BODY & CONTAINER |
||||
------------------------------------- */ |
||||
body { |
||||
background-color: #f6f6f6; |
||||
} |
||||
|
||||
.body-wrap { |
||||
background-color: #f6f6f6; |
||||
width: 100%; |
||||
} |
||||
|
||||
.container, .container-table { |
||||
width: 600px; |
||||
max-width: 600px !important; |
||||
display: block !important; |
||||
/* makes it centered */ |
||||
clear: both !important; |
||||
margin: 0 auto !important; |
||||
} |
||||
|
||||
.content { |
||||
max-width: 600px; |
||||
margin: 0 auto; |
||||
display: block; |
||||
font-size: 0; |
||||
line-height: 0; |
||||
padding-bottom: 20px; |
||||
} |
||||
|
||||
.content-banner { |
||||
padding-top: 20px; |
||||
} |
||||
|
||||
/* ------------------------------------- |
||||
LOGO, HEADER, FOOTER, MAIN |
||||
------------------------------------- */ |
||||
.logo { |
||||
padding: 20px 0 10px; |
||||
text-align: center; |
||||
} |
||||
|
||||
.banner, .banner img { |
||||
font-size: 0; |
||||
line-height: 0; |
||||
} |
||||
|
||||
.main { |
||||
background-color: white; |
||||
border: 1px solid #e9e9e9; |
||||
border-radius: 3px; |
||||
} |
||||
|
||||
.content-banner .main { |
||||
border-top-left-radius: 0; |
||||
border-top-right-radius: 0; |
||||
border-top: none; |
||||
} |
||||
|
||||
.content-wrap { |
||||
padding: 20px; |
||||
} |
||||
|
||||
.content-block { |
||||
padding: 0 0 10px; |
||||
} |
||||
|
||||
.content-block img { |
||||
max-width: 100%; |
||||
height: auto; |
||||
display: block; |
||||
} |
||||
|
||||
.content-block-spaced { |
||||
padding: 0 0 25px; |
||||
} |
||||
|
||||
.indented { |
||||
padding-left: 20px; |
||||
} |
||||
|
||||
.li { |
||||
padding-left: 10px; |
||||
} |
||||
|
||||
.footer { |
||||
width: 100%; |
||||
clear: both; |
||||
margin-top: 15px; |
||||
} |
||||
|
||||
.footer, .footer p, .footer a, .footer td, .footer br { |
||||
color: #999; |
||||
font-size: 12px; |
||||
line-height: 20px; |
||||
} |
||||
|
||||
.footer .social-icons table { |
||||
margin: 0 auto; |
||||
} |
||||
|
||||
.footer .social-icons td { |
||||
padding: 0 10px; |
||||
} |
||||
|
||||
/* ------------------------------------- |
||||
TYPOGRAPHY |
||||
------------------------------------- */ |
||||
.h3 { |
||||
font-size: 18px; |
||||
line-height: 25px; |
||||
font-weight: bold; |
||||
} |
||||
|
||||
.biglink a { |
||||
font-size: 20px; |
||||
} |
||||
|
||||
/* ------------------------------------- |
||||
LINKS & BUTTONS |
||||
------------------------------------- */ |
||||
a { |
||||
color: #3c8dbc; |
||||
text-decoration: underline; |
||||
} |
||||
|
||||
.btn-primary { |
||||
text-decoration: none; |
||||
color: white; |
||||
background-color: #3c8dbc; |
||||
border: solid #3c8dbc; |
||||
border-width: 10px 20px; |
||||
line-height: 2em; |
||||
font-weight: bold; |
||||
text-align: center; |
||||
cursor: pointer; |
||||
display: inline-block; |
||||
border-radius: 5px; |
||||
text-transform: capitalize; |
||||
} |
||||
|
||||
/* ------------------------------------- |
||||
OTHER STYLES THAT MIGHT BE USEFUL |
||||
------------------------------------- */ |
||||
.last { |
||||
margin-bottom: 0; |
||||
padding-bottom: 0; |
||||
} |
||||
|
||||
.first { |
||||
margin-top: 0; |
||||
padding-top: 0; |
||||
} |
||||
|
||||
.aligncenter { |
||||
text-align: center; |
||||
} |
||||
|
||||
.alignright { |
||||
text-align: right; |
||||
} |
||||
|
||||
.alignleft { |
||||
text-align: left; |
||||
} |
||||
|
||||
.clear { |
||||
clear: both; |
||||
} |
||||
|
||||
/* ------------------------------------- |
||||
ALERTS |
||||
Change the class depending on warning email, good email or bad email |
||||
------------------------------------- */ |
||||
.alert { |
||||
font-size: 16px; |
||||
color: #fff; |
||||
font-weight: 500; |
||||
padding: 20px; |
||||
text-align: center; |
||||
border-radius: 3px 3px 0 0; |
||||
} |
||||
|
||||
.alert a { |
||||
color: white; |
||||
text-decoration: none; |
||||
font-weight: 500; |
||||
font-size: 16px; |
||||
} |
||||
|
||||
.alert.alert-warning { |
||||
background-color: #FF9F00; |
||||
} |
||||
|
||||
.alert.alert-bad { |
||||
background-color: #D0021B; |
||||
} |
||||
|
||||
.alert.alert-good { |
||||
background-color: #68B90F; |
||||
} |
||||
|
||||
/* ------------------------------------- |
||||
RESPONSIVE AND MOBILE FRIENDLY STYLES |
||||
------------------------------------- */ |
||||
@media only screen and (max-width: 600px) { |
||||
body { |
||||
padding: 0 !important; |
||||
} |
||||
|
||||
.container, .container-table { |
||||
padding: 0 !important; |
||||
width: 100% !important; |
||||
} |
||||
|
||||
.content { |
||||
padding: 0 0 10px 0 !important; |
||||
} |
||||
|
||||
.content-wrap { |
||||
padding: 10px !important; |
||||
} |
||||
|
||||
.invoice { |
||||
width: 100% !important; |
||||
} |
||||
|
||||
.main { |
||||
border-right: none !important; |
||||
border-left: none !important; |
||||
border-radius: 0 !important; |
||||
} |
||||
|
||||
.logo { |
||||
padding-top: 10px !important; |
||||
} |
||||
|
||||
.footer { |
||||
margin-top: 10px !important; |
||||
} |
||||
|
||||
.indented { |
||||
padding-left: 10px; |
||||
} |
||||
} |
||||
@ -1,85 +0,0 @@
@@ -1,85 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
||||
<html xmlns="http://www.w3.org/1999/xhtml"> |
||||
<head> |
||||
<meta name="viewport" content="width=device-width" /> |
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> |
||||
<title>Announcement</title> |
||||
<link href="../styles.css" media="all" rel="stylesheet" type="text/css" /> |
||||
</head> |
||||
|
||||
<body> |
||||
<table class="body-wrap" cellpadding="0" cellspacing="0"> |
||||
<tr> |
||||
<td class="container" align="center"> |
||||
<table cellpadding="0" cellspacing="0" class="container-table"> |
||||
<tr> |
||||
<td class="content content-banner" align="center"> |
||||
<a href="#" title="" target="_blank" class="banner"> |
||||
<img src="https://placeholdit.imgix.net/~text?txtsize=33&txt=Announcement%20Image&w=600&h=158" |
||||
width="600" alt="" /> |
||||
</a> |
||||
<table class="main" width="100%" cellpadding="0" cellspacing="0"> |
||||
<tr> |
||||
<td class="content-wrap"> |
||||
<table width="100%" cellpadding="0" cellspacing="0"> |
||||
<tr> |
||||
<td class="h3 content-block"> |
||||
A title! |
||||
</td> |
||||
</tr> |
||||
<tr> |
||||
<td class="content-block"> |
||||
Some text about an announcement. |
||||
</td> |
||||
</tr> |
||||
<tr> |
||||
<td class="content-block indented"> |
||||
<table width="100%" cellpadding="0" cellspacing="0"> |
||||
<tr> |
||||
<td width="15">•</td> |
||||
<td class="li">Bullet 1</td> |
||||
</tr> |
||||
<tr> |
||||
<td>•</td> |
||||
<td class="li">Bullet 2</td> |
||||
</tr> |
||||
</table> |
||||
</td> |
||||
</tr> |
||||
<tr> |
||||
<td class="content-block last"> |
||||
Thank you!<br /> |
||||
The Bitwarden Team |
||||
</td> |
||||
</tr> |
||||
</table> |
||||
</td> |
||||
</tr> |
||||
</table> |
||||
<table class="footer" cellpadding="0" cellspacing="0" width="100%"> |
||||
<tr> |
||||
<td class="aligncenter content-block"> |
||||
8bit Solutions LLC<br /> |
||||
You can <a href="[unsubscribe]">unsubscribe</a> from future mailings. |
||||
</td> |
||||
</tr> |
||||
<tr> |
||||
<td class="aligncenter social-icons" align="center"> |
||||
<table cellpadding="0" cellspacing="0"> |
||||
<tr> |
||||
<td><a href="https://twitter.com/bitwarden_app" target="_blank"><img src="https://bitwarden.com/images/mail-twitter.png" alt="Twitter" width="30" height="30" /></a></td> |
||||
<td><a href="https://www.facebook.com/bitwarden/" target="_blank"><img src="https://bitwarden.com/images/mail-facebook.png" alt="Facebook" width="30" height="30" /></a></td> |
||||
<td><a href="https://plus.google.com/+bitwarden" target="_blank"><img src="https://bitwarden.com/images/mail-gplus.png" alt="Google+" width="30" height="30" /></a></td> |
||||
</tr> |
||||
</table> |
||||
</td> |
||||
</tr> |
||||
</table> |
||||
</td> |
||||
</tr> |
||||
</table> |
||||
</td> |
||||
</tr> |
||||
</table> |
||||
</body> |
||||
</html> |
||||
@ -1,146 +0,0 @@
@@ -1,146 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
||||
<html xmlns="http://www.w3.org/1999/xhtml"> |
||||
<head> |
||||
<meta name="viewport" content="width=device-width" /> |
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> |
||||
<title>Welcome</title> |
||||
<link href="../styles.css" media="all" rel="stylesheet" type="text/css" /> |
||||
</head> |
||||
|
||||
<body> |
||||
<table class="body-wrap" cellpadding="0" cellspacing="0"> |
||||
<tr> |
||||
<td valign="middle" class="aligncenter middle logo"> |
||||
<img src="https://bitwarden.com/images/logo-gray.png" alt="" width="250" height="39" /> |
||||
</td> |
||||
</tr> |
||||
<tr> |
||||
<td class="container" align="center"> |
||||
<table cellpadding="0" cellspacing="0" class="container-table"> |
||||
<tr> |
||||
<td class="content" align="center"> |
||||
<table class="main" width="100%" cellpadding="0" cellspacing="0"> |
||||
<tr> |
||||
<td class="content-wrap"> |
||||
<table width="100%" cellpadding="0" cellspacing="0"> |
||||
<tr> |
||||
<td class="content-block"> |
||||
Thank you for creating an account with Bitwarden. You may now log in with your new account. |
||||
</td> |
||||
</tr> |
||||
<tr> |
||||
<td class="content-block"> |
||||
Did you know that Bitwarden is free to sync with all of your devices? Download Bitwarden today on: |
||||
</td> |
||||
</tr> |
||||
<tr> |
||||
<td class="h3"> |
||||
Desktop |
||||
</td> |
||||
</tr> |
||||
<tr> |
||||
<td class="content-block"> |
||||
Access Bitwarden on Windows, macOS, and Linux desktops with our native desktop application. |
||||
</td> |
||||
</tr> |
||||
<tr> |
||||
<td class="content-block"> |
||||
<a href="https://bitwarden.com/#download" target="_blank"> |
||||
<img src="https://bitwarden.com/images/mail-os.png" alt="Windows, macOS, and Linux" width="550" height="110" /> |
||||
</a> |
||||
</td> |
||||
</tr> |
||||
<tr> |
||||
<td class="h3"> |
||||
Web Browser |
||||
</td> |
||||
</tr> |
||||
<tr> |
||||
<td class="content-block"> |
||||
Integrate Bitwarden directly into your favorite browser. Use our browser extensions for a seamless browsing experience. |
||||
</td> |
||||
</tr> |
||||
<tr> |
||||
<td class="content-block"> |
||||
<a href="https://bitwarden.com/#download-browser" target="_blank"> |
||||
<img src="https://bitwarden.com/images/mail-browsers.png" alt="Chrome, Firefox, Opera, Edge, Safari, and more" width="550" height="90" /> |
||||
</a> |
||||
</td> |
||||
</tr> |
||||
<tr> |
||||
<td class="h3"> |
||||
Mobile |
||||
</td> |
||||
</tr> |
||||
<tr> |
||||
<td class="content-block"> |
||||
Take Bitwarden on the go with our mobile apps for your phone or tablet device. |
||||
</td> |
||||
</tr> |
||||
<tr> |
||||
<td class="content-block"> |
||||
<a href="https://bitwarden.com/#download-mobile" target="_blank"> |
||||
<img src="https://bitwarden.com/images/mail-stores.png" alt="App Store and Google Play" width="550" height="85" /> |
||||
</a> |
||||
</td> |
||||
</tr> |
||||
<tr> |
||||
<td class="h3"> |
||||
Web |
||||
</td> |
||||
</tr> |
||||
<tr> |
||||
<td> |
||||
Stuck without any of your devices? Using a friend's computer? You can access your Bitwarden vault from any web enabled device by using the web vault. |
||||
</td> |
||||
</tr> |
||||
<tr> |
||||
<td class="content-block h3 biglink"> |
||||
<a target="_blank" href="https://vault.bitwarden.com/?utm_source=welcome_email&utm_medium=email">vault.bitwarden.com</a> |
||||
<br /> |
||||
<br /> |
||||
</td> |
||||
</tr> |
||||
<tr> |
||||
<td class="content-block"> |
||||
If you have any questions or problems you can email us from our website at <a target="_blank" href="https://bitwarden.com/contact/?utm_source=welcome_email&utm_medium=email">https://bitwarden.com/contact</a>. |
||||
</td> |
||||
</tr> |
||||
<tr> |
||||
<td class="content-block last"> |
||||
Thank you!<br /> |
||||
The Bitwarden Team |
||||
</td> |
||||
</tr> |
||||
</table> |
||||
</td> |
||||
</tr> |
||||
</table> |
||||
<table class="footer" cellpadding="0" cellspacing="0" width="100%"> |
||||
<tr> |
||||
<td class="aligncenter content-block"> |
||||
8bit Solutions LLC |
||||
</td> |
||||
</tr> |
||||
<tr> |
||||
<td class="aligncenter social-icons" align="center"> |
||||
<table cellpadding="0" cellspacing="0"> |
||||
<tr> |
||||
<td><a href="https://twitter.com/bitwarden_app" target="_blank"><img src="https://bitwarden.com/images/mail-twitter.png" alt="Twitter" width="30" height="30" /></a></td> |
||||
<td><a href="https://www.facebook.com/bitwarden/" target="_blank"><img src="https://bitwarden.com/images/mail-facebook.png" alt="Facebook" width="30" height="30" /></a></td> |
||||
<td><a href="https://plus.google.com/+bitwarden" target="_blank"><img src="https://bitwarden.com/images/mail-gplus.png" alt="Google+" width="30" height="30" /></a></td> |
||||
<td><a href="https://github.com/bitwarden" target="_blank"><img src="https://bitwarden.com/images/mail-github.png" alt="GitHub" width="30" height="30" /></a></td> |
||||
</tr> |
||||
</table> |
||||
</td> |
||||
</tr> |
||||
</table> |
||||
</td> |
||||
</tr> |
||||
</table> |
||||
</td> |
||||
</tr> |
||||
</table> |
||||
</body> |
||||
</html> |
||||
|
||||
Loading…
Reference in new issue