diff --git a/.deployment b/.deployment
new file mode 100644
index 00000000..9d7d31aa
--- /dev/null
+++ b/.deployment
@@ -0,0 +1,2 @@
+[config]
+project = src\Server\OneTrueError.Web\OneTrueError.Web.csproj
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 00000000..7607d65e
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,56 @@
+# EditorConfig: http://EditorConfig.org
+
+# top-most EditorConfig file
+root = true
+
+# Don't use tabs for indentation.
+[*]
+indent_style = space
+# (Please don't specify an indent_size here; that has too many unintended consequences.)
+
+# Code files
+[*.{cs,csx,vb,vbx}]
+indent_size = 4
+
+# Xml project files
+[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}]
+indent_size = 2
+
+# Xml config files
+[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}]
+indent_size = 2
+
+# JSON files
+[*.json]
+indent_size = 2
+
+# Dotnet code style settings:
+[*.cs]
+# Sort using and Import directives with System.* appearing first
+dotnet_sort_system_directives_first = true
+
+# Don't use this. qualifier
+dotnet_style_qualification_for_field = false:suggestion
+dotnet_style_qualification_for_property = false:suggestion
+
+# use int x = .. over Int32
+dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
+
+# use int.MaxValue over Int32.MaxValue
+dotnet_style_predefined_type_for_member_access = true:suggestion
+
+# Require var all the time.
+csharp_style_var_for_built_in_types = true:suggestion
+csharp_style_var_when_type_is_apparent = true:suggestion
+csharp_style_var_elsewhere = true:suggestion
+
+# Disallow throw expressions.
+csharp_style_throw_expression = false:suggestion
+
+# Newline settings
+csharp_new_line_before_open_brace = all
+csharp_new_line_before_else = true
+csharp_new_line_before_catch = true
+csharp_new_line_before_finally = true
+csharp_new_line_before_members_in_object_initializers = true
+csharp_new_line_before_members_in_anonymous_types = true
diff --git a/.gitattributes b/.gitattributes
index ceba70d8..1ff0c423 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,22 +1,63 @@
-# Set the default behavior, in case people don't have core.autocrlf set.
+###############################################################################
+# Set default behavior to automatically normalize line endings.
+###############################################################################
* text=auto
-# Explicitly declare text files you want to always be normalized and converted
-# to native line endings on checkout.
-#*.c text
-#*.h text
+###############################################################################
+# Set default behavior for command prompt diff.
+#
+# This is need for earlier builds of msysgit that does not have it on by
+# default for csharp files.
+# Note: This is only used by command line
+###############################################################################
+#*.cs diff=csharp
-# Declare files that will always have CRLF line endings on checkout.
-*.sln text eol=crlf
-*.csproj text filter=csprojarrange
-*.cs text eol=crlf
-*.cshtml text eol=crlf
-*.ts text eol=crlf
+###############################################################################
+# Set the merge driver for project and solution files
+#
+# Merging from the command prompt will add diff markers to the files if there
+# are conflicts (Merging from VS is not affected by the settings below, in VS
+# the diff markers are never inserted). Diff markers may cause the following
+# file extensions to fail to load in VS. An alternative would be to treat
+# these files as binary and thus will always conflict and require user
+# intervention with every merge. To do so, just uncomment the entries below
+###############################################################################
+#*.sln merge=binary
+#*.csproj merge=binary
+#*.vbproj merge=binary
+#*.vcxproj merge=binary
+#*.vcproj merge=binary
+#*.dbproj merge=binary
+#*.fsproj merge=binary
+#*.lsproj merge=binary
+#*.wixproj merge=binary
+#*.modelproj merge=binary
+#*.sqlproj merge=binary
+#*.wwaproj merge=binary
-# Denote all files that are truly binary and should not be modified.
-*.png binary
-*.jpg binary
-*.gif binary
-*.obj binary
-*.exe binary
-*.dll binary
+###############################################################################
+# behavior for image files
+#
+# image files are treated as binary by default.
+###############################################################################
+#*.jpg binary
+#*.png binary
+#*.gif binary
+
+###############################################################################
+# diff behavior for common document formats
+#
+# Convert binary document formats to text before diffing them. This feature
+# is only available from the command line. Turn it on by uncommenting the
+# entries below.
+###############################################################################
+#*.doc diff=astextplain
+#*.DOC diff=astextplain
+#*.docx diff=astextplain
+#*.DOCX diff=astextplain
+#*.dot diff=astextplain
+#*.DOT diff=astextplain
+#*.pdf diff=astextplain
+#*.PDF diff=astextplain
+#*.rtf diff=astextplain
+#*.RTF diff=astextplain
diff --git a/.gitignore b/.gitignore
index b72cfb21..bcbac429 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,10 +26,16 @@ Thumbs.db
obj/
[Rr]elease*/
_ReSharper*/
-[Tt]est[Rr]esult*
*/packages/*/
-src/*/.vs/*
-src/*/packages/*/
+**/.vs/*
+**/packages/*/
src/Tools/MarkdownToNamespaceDoc/packages/*/
src/Tools/TsGenerator/.vs/*
src/Help/*
+**/.vs/*
+src/Server/Coderr.Server.Web.Tests/applicationhost.config
+/src/Server/Coderr.Server.Web/node_modules/*
+/src/Server/Coderr.Server.Web/wwwroot/dist/**
+/src/Server/Coderr.Server.Web/npm-shrinkwrap.json
+/src/Server/node_modules/**
+/src/Server/Coderr.Server.WebSite/ClientApp/.angular/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 00000000..958489da
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+Coderr Server
+Copyright (C) 2018 1TCompany AB
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see .
+
+------------
+
+More information is found here:
+
+https://coderr.io/features/
diff --git a/LICENSE.txt b/LICENSE.txt
deleted file mode 100644
index efbadd1e..00000000
--- a/LICENSE.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-OneTrueError Server
-Copyright (C) 2016 Gauffin Interactive AB
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see .
-
-------------
-
-More information is found here:
-
-http://onetrueerror.com/licensing/
diff --git a/ReadMe.md b/ReadMe.md
index e871792b..2be6ab99 100644
--- a/ReadMe.md
+++ b/ReadMe.md
@@ -1,22 +1,77 @@
-OneTrueError
-================================
+Coderr Community Server
+=============================
-OneTrueError is an open source error handling service for .NET. It includes the context information that you forgot to include when you logged/reported the exception.
+[]() []()
-
+# Solve errors more quickly
+It works on my machine!
-[Getting started guide](https://www.codeproject.com/articles/1126297/onetrueerror-automated-exception-handling)
+We all have heard, and said, that expression. Solving errors can be quite frustrating. Even trivial errors which just takes a few minutes to solve can cause frustration if there are many of them.
+Coderr automates the error management process. Let Coderr detect, report and analyze the errors, so that you can focus on just solving them.
-## Love or hate our service?
+
-Please write a review.
+## Search function
-* [G2 Crowd](https://www.g2crowd.com/products/onetrueerror/reviews)
+
+.. don't want to host/maintain your own server? Try [Coderr Cloud](https://lobby.coderr.io/?utm_source=github) - Free up to five users.
+
+## Getting started
+
+1. [Download Coderr Server](https://github.com/coderrio/Coderr.Server/releases), use our [cloud service](https://lobby.coderr.io) (free for up to five users) or use our [Docker image]()
+2. Install one of our [nuget libraries](https://www.nuget.org/packages?q=coderr.client) (or one of the [js libraries](https://www.npmjs.com/package/coderr.client)).
+3. Follow the instructions in the package ReadMe (max three lines of code to get started).
+4. Try the code below.
+
+**Unhandled exceptions will automatically be reported by the client libraries.**
+
+To report exceptions manually:
+
+```csharp
+public void UpdatePost(int uid, ForumPost post)
+{
+ try
+ {
+ _service.Update(uid, post);
+ }
+ catch (Exception ex)
+ {
+ Err.Report(ex, new{ UserId = uid, ForumPost = post });
+ }
+}
+```
+
+Sample data collected by the ASP.NET Core MVC library:
+
+
+
+You can learn more about reporting errors [here](https://coderr.io/documentation/getting-started).
+
+## Running Coderr
+
+You can run any Coderr in development, test and in production. Coderr is available in three different ways; as Coderr Community Server (AGPL license, self-hosting), as Coderr Cloud (commercial license, cloud version) or on request, as Coderr Premise (commercial license, self-hosting version). Coderr Cloud and Coderr Premise add powerful algorithms to prioritize errors and provide insight to how your code is improving over time with applied solutions.
+
+[Read more](https://coderr.io/features/)
+
+
+## About us
+
+We are passionate about Open Source, Microsoft .NET and code quality. 1TCompany started in 2017 in Sweden and builds on years of coding experience and bringing products to market. Our mission is to assist fellow developers deliver quality code. To accomplish this mission, we decided to make Coderr commercially available and ready for prime time.
+
+
+## Community
+
+* [Discussion board](http://discuss.coderr.io)
+* [Report bugs](https://github.com/coderr.io/coderr.server/issues)
+* [Documentation](https://coderr.io/documentation)
+* [Commercial support](mailto:support@coderr.io?subject=Commercial%20support%20inquiry)
## Licensing
-* Server: AGPL
-* Client libraries: Apache 2.0
+* Community Server: [AGPL](License)
+* Client libraries: [Apache 2.0](https://opensource.org/licenses/apache-2.0)
+* [Coderr Cloud](https://lobby.coderr.io): Commercial
+* [Coderr Premise](https://coderr.io/features): Commercial
diff --git a/CodeOfConduct.md b/docs/CODE_OF_CONDUCT.md
similarity index 100%
rename from CodeOfConduct.md
rename to docs/CODE_OF_CONDUCT.md
diff --git a/Contribute.md b/docs/Contributing.md
similarity index 100%
rename from Contribute.md
rename to docs/Contributing.md
diff --git a/docs/collections.gif b/docs/collections.gif
new file mode 100644
index 00000000..22c90a78
Binary files /dev/null and b/docs/collections.gif differ
diff --git a/docs/discover-incident.png b/docs/discover-incident.png
new file mode 100644
index 00000000..cafd084d
Binary files /dev/null and b/docs/discover-incident.png differ
diff --git a/docs/release_banner.png b/docs/release_banner.png
new file mode 100644
index 00000000..c359c920
Binary files /dev/null and b/docs/release_banner.png differ
diff --git a/docs/search.png b/docs/search.png
new file mode 100644
index 00000000..4d5830a1
Binary files /dev/null and b/docs/search.png differ
diff --git a/screenshot.png b/screenshot.png
deleted file mode 100644
index 9ba22894..00000000
Binary files a/screenshot.png and /dev/null differ
diff --git a/src/DockerCompose/Linux/docker-compose.yml b/src/DockerCompose/Linux/docker-compose.yml
new file mode 100644
index 00000000..8dbfafa5
--- /dev/null
+++ b/src/DockerCompose/Linux/docker-compose.yml
@@ -0,0 +1,20 @@
+version: "3.7"
+
+services:
+
+ coderr-server-web:
+ image: "coderrio/coderrserverweb:latest"
+ container_name: coderr-server-web
+ hostname: coderr-server-web
+ ports:
+ - "2500:80"
+ networks:
+ - coderr_network
+
+volumes:
+ esdata:
+ driver: local
+
+networks:
+ coderr_network:
+ name: coderr_network
diff --git a/src/DockerCompose/Linux/run example.txt b/src/DockerCompose/Linux/run example.txt
new file mode 100644
index 00000000..bceadf67
--- /dev/null
+++ b/src/DockerCompose/Linux/run example.txt
@@ -0,0 +1 @@
+docker-compose run -p 2500:80 -e "ConnectionStrings:Db"="Data Source=host.docker.internal,1433;Initial Catalog=Coderr99;User Id=sa; Password=Pass@word; Connect Timeout=15;" coderr-server-web
\ No newline at end of file
diff --git a/src/DockerCompose/Windows/docker-compose.yml b/src/DockerCompose/Windows/docker-compose.yml
new file mode 100644
index 00000000..1e638ebb
--- /dev/null
+++ b/src/DockerCompose/Windows/docker-compose.yml
@@ -0,0 +1,29 @@
+version: "3.7"
+
+services:
+
+ coderr-server-web:
+ image: "coderrio/communityserver-win:latest"
+ container_name: coderr_communityserver
+ hostname: coderr
+ environment:
+ - ASPNETCORE_ENVIRONMENT=Production
+ - ASPNETCORE_URLS=http://+:5000
+
+ # To enable https, use these lines and configure a certificate
+ #- ASPNETCORE_URLS=https://+:5001;http://+:5000
+ #- ASPNETCORE_HTTPS_PORT=5001
+
+ # Adjust the connection string
+ - CODERR_CONNECTIONSTRING=Data Source=host.docker.internal,1433;Initial Catalog=Coderr;Integrated Security=false;Connect Timeout=15;user=coderr;password=c0d3rr
+
+ # Comment out this line once Coderr have been configured (run through the install wizard)
+ # and then restart the container.
+ - CODERR_CONFIG_PASSWORD=changeThis
+
+ volumes:
+ - ${APPDATA}/Microsoft/UserSecrets:C:\ProtectedStorage:rw
+
+ ports:
+ - "60473:5000/tcp"
+ - "60474:5001"
diff --git a/src/DockerCompose/Windows/run example.txt b/src/DockerCompose/Windows/run example.txt
new file mode 100644
index 00000000..0a7f926f
--- /dev/null
+++ b/src/DockerCompose/Windows/run example.txt
@@ -0,0 +1 @@
+docker-compose run -p 2500:80 -e "ConnectionStrings:Db"="Data Source=172.**.**.1,1433;Initial Catalog=Coderr99;User Id=sa; Password=Pass@word; Connect Timeout=15;" coderr-server-web
\ No newline at end of file
diff --git a/src/Server/.dockerignore b/src/Server/.dockerignore
new file mode 100644
index 00000000..c947c5af
--- /dev/null
+++ b/src/Server/.dockerignore
@@ -0,0 +1,34 @@
+# directories
+**/bin/
+**/obj/
+**/out/
+
+# files
+Dockerfile*
+#**/*.md
+
+**/.classpath
+**/.dockerignore
+**/.env
+**/.git
+**/.gitignore
+**/.project
+**/.settings
+**/.toolstarget
+**/.vs
+**/.vscode
+**/*.*proj.user
+**/*.dbmdl
+**/*.jfm
+**/azds.yaml
+**/bin
+**/charts
+**/docker-compose*
+**/Dockerfile*
+**/node_modules
+**/npm-debug.log
+**/obj
+**/secrets.dev.yaml
+**/values.dev.yaml
+LICENSE
+README.md
diff --git a/src/Server/Coderr.Server.Abstractions/Boot/ConfigurationContext.cs b/src/Server/Coderr.Server.Abstractions/Boot/ConfigurationContext.cs
new file mode 100644
index 00000000..4f905a70
--- /dev/null
+++ b/src/Server/Coderr.Server.Abstractions/Boot/ConfigurationContext.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Data;
+using System.Reflection;
+using System.Security.Claims;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace Coderr.Server.Abstractions.Boot
+{
+ public abstract class ConfigurationContext
+ {
+ protected ConfigurationContext(IServiceCollection services, Func serviceProvider)
+ {
+ Services = services;
+ ServiceProvider = serviceProvider;
+ }
+
+ public Func ConnectionFactory { get; set; }
+ public IServiceCollection Services { get; private set; }
+ public Func ServiceProvider { get; private set; }
+ public IConfiguration Configuration { get; set; }
+
+ public abstract void RegisterMessageTypes(Assembly assembly);
+
+ public abstract ConfigurationContext Clone(IServiceCollection serviceCollection);
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Abstractions/Boot/ContainerServiceAttribute.cs b/src/Server/Coderr.Server.Abstractions/Boot/ContainerServiceAttribute.cs
new file mode 100644
index 00000000..1a0a61f1
--- /dev/null
+++ b/src/Server/Coderr.Server.Abstractions/Boot/ContainerServiceAttribute.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace Coderr.Server.Abstractions.Boot
+{
+ public class ContainerServiceAttribute: Attribute
+ {
+ public bool IsSingleInstance { get; set; }
+ public bool IsTransient { get; set; }
+ public bool RegisterAsSelf { get; set; }
+ }
+}
diff --git a/src/Server/Coderr.Server.Abstractions/Boot/IAppModule.cs b/src/Server/Coderr.Server.Abstractions/Boot/IAppModule.cs
new file mode 100644
index 00000000..4abb10c3
--- /dev/null
+++ b/src/Server/Coderr.Server.Abstractions/Boot/IAppModule.cs
@@ -0,0 +1,10 @@
+namespace Coderr.Server.Abstractions.Boot
+{
+ public interface IAppModule
+ {
+ void Configure(ConfigurationContext context);
+ void Start(StartContext context);
+
+ void Stop();
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Abstractions/Boot/IConfiguration.cs b/src/Server/Coderr.Server.Abstractions/Boot/IConfiguration.cs
new file mode 100644
index 00000000..15fc8d69
--- /dev/null
+++ b/src/Server/Coderr.Server.Abstractions/Boot/IConfiguration.cs
@@ -0,0 +1,13 @@
+using System.Collections.Generic;
+
+namespace Coderr.Server.Abstractions.Boot
+{
+ public interface IConfiguration
+ {
+ string this[string name] { get; }
+ IConfigurationSection GetSection(string name);
+ string GetConnectionString(string name);
+ IEnumerable GetChildren();
+ }
+
+}
diff --git a/src/Server/Coderr.Server.Abstractions/Boot/IConfigurationSection.cs b/src/Server/Coderr.Server.Abstractions/Boot/IConfigurationSection.cs
new file mode 100644
index 00000000..cadf5bd0
--- /dev/null
+++ b/src/Server/Coderr.Server.Abstractions/Boot/IConfigurationSection.cs
@@ -0,0 +1,16 @@
+using System.Collections.Generic;
+
+namespace Coderr.Server.Abstractions.Boot
+{
+ ///
+ /// Abstraction for the .NET Core configuration files.
+ ///
+ public interface IConfigurationSection
+ {
+ string this[string name] { get; }
+ IEnumerable GetChildren();
+
+ string Value { get; }
+ }
+
+}
diff --git a/src/Server/Coderr.Server.Abstractions/Boot/RegisterExtensions.cs b/src/Server/Coderr.Server.Abstractions/Boot/RegisterExtensions.cs
new file mode 100644
index 00000000..7cf4503d
--- /dev/null
+++ b/src/Server/Coderr.Server.Abstractions/Boot/RegisterExtensions.cs
@@ -0,0 +1,88 @@
+using System;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace Coderr.Server.Abstractions.Boot
+{
+ public static class RegisterExtensions
+ {
+
+ public static void RegisterContainerServices(this IServiceCollection serviceCollection, Assembly assembly, [CallerMemberName] string callerName = "")
+ {
+ var gotWrongAttribute = (
+ from type in assembly.GetTypes()
+ let attributes = type.GetCustomAttributes()
+ where attributes.Count(x => x.GetType().FullName == "Griffin.Container.ContainerService") > 0
+ select type).ToList();
+ if (gotWrongAttribute.Count > 0)
+ {
+ throw new InvalidOperationException(
+ $"Types \'{string.Join(",", gotWrongAttribute)}\' was decorated with the wrong attribute");
+ }
+
+ var containerServices = assembly.GetTypes()
+ .Where(x => x.GetCustomAttribute() != null);
+
+ foreach (var containerService in containerServices)
+ {
+ var attr = containerService.GetCustomAttribute();
+ var interfaces = containerService.GetInterfaces();
+ var lifetime = ConvertLifetime(attr);
+
+ // Hack so that the same instance is resolved for each interface
+ bool isRegisteredAsSelf = false;
+ if (interfaces.Length > 1 || attr.RegisterAsSelf)
+ {
+ serviceCollection.Add(new ServiceDescriptor(containerService, containerService, lifetime));
+ isRegisteredAsSelf = true;
+ }
+
+
+ foreach (var @interface in interfaces)
+ {
+ var sd = isRegisteredAsSelf
+ ? new ServiceDescriptor(@interface, x => x.GetService(containerService), lifetime) // else we don't get the same instance in the scope.
+ : new ServiceDescriptor(@interface, containerService, lifetime);
+ serviceCollection.Add(sd);
+ }
+ }
+ }
+
+ public static void RegisterMessageHandlers(this IServiceCollection serviceCollection, Assembly assembly, [CallerMemberName] string callerName = "")
+ {
+ var types = assembly.GetTypes()
+ .Where(y => y.GetInterfaces()
+ .Any(x => x.Name.Contains("IMessageHandler") || x.Name.Contains("IQueryHandler")))
+ .ToList();
+ foreach (var type in types)
+ {
+ serviceCollection.AddScoped(type, type);
+
+ var ifs = type.GetInterfaces()
+ .Where(x => x.Name.Contains("IMessageHandler") || x.Name.Contains("IQueryHandler"))
+ .ToList();
+ foreach (var @if in ifs)
+ {
+ serviceCollection.AddScoped(@if, x => x.GetService(type));
+ }
+ }
+ }
+
+ private static ServiceLifetime ConvertLifetime(ContainerServiceAttribute attr)
+ {
+ if (attr.IsSingleInstance)
+ {
+ return ServiceLifetime.Singleton;
+ }
+
+ if (attr.IsTransient)
+ {
+ return ServiceLifetime.Transient;
+ }
+
+ return ServiceLifetime.Scoped;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Abstractions/Boot/StartContext.cs b/src/Server/Coderr.Server.Abstractions/Boot/StartContext.cs
new file mode 100644
index 00000000..ef029532
--- /dev/null
+++ b/src/Server/Coderr.Server.Abstractions/Boot/StartContext.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace Coderr.Server.Abstractions.Boot
+{
+ public class StartContext
+ {
+ public IServiceProvider ServiceProvider { get; set; }
+ }
+
+}
diff --git a/src/Server/Coderr.Server.Abstractions/Coderr.Server.Abstractions.csproj b/src/Server/Coderr.Server.Abstractions/Coderr.Server.Abstractions.csproj
new file mode 100644
index 00000000..5306ba1d
--- /dev/null
+++ b/src/Server/Coderr.Server.Abstractions/Coderr.Server.Abstractions.csproj
@@ -0,0 +1,16 @@
+
+
+
+ netstandard2.0
+ Debug;Release;Premise
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Server/Coderr.Server.Abstractions/Config/ConfigurationCategoryExtensions.cs b/src/Server/Coderr.Server.Abstractions/Config/ConfigurationCategoryExtensions.cs
new file mode 100644
index 00000000..36fd5150
--- /dev/null
+++ b/src/Server/Coderr.Server.Abstractions/Config/ConfigurationCategoryExtensions.cs
@@ -0,0 +1,80 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+
+namespace Coderr.Server.Abstractions.Config
+{
+ ///
+ /// Extensions used to convert between a flat object and a configuration dictionary
+ ///
+ public static class ConfigurationCategoryExtensions
+ {
+ ///
+ /// Assign properties from the configuration dictionary.
+ ///
+ /// Category that should get its properties assigned
+ /// Dictionary containing the property values.
+ /// section;settings
+ public static void AssignProperties(this IConfigurationSection section, IDictionary settings)
+ {
+ if (section == null) throw new ArgumentNullException("section");
+ if (settings == null) throw new ArgumentNullException("settings");
+ var type = section.GetType();
+ foreach (var kvp in settings)
+ {
+ var property = type.GetProperty(kvp.Key);
+ if (property == null)
+ continue;
+
+ var propertyType = property.PropertyType;
+ if (propertyType == typeof(Uri))
+ {
+ var value = new Uri(kvp.Value);
+ property.SetValue(section, value);
+ }
+ else if (!propertyType.IsAssignableFrom(typeof(string)))
+ {
+ var realType = Nullable.GetUnderlyingType(propertyType);
+ if (realType != null)
+ {
+ // we got a nullable type and the string represents
+ // null, so just assign it.
+ if (string.IsNullOrEmpty(kvp.Value))
+ {
+ property.SetValue(section, null);
+ continue;
+ }
+
+ propertyType = realType;
+ }
+
+ var value = Convert.ChangeType(kvp.Value, propertyType);
+ property.SetValue(section, value);
+ }
+ else
+ property.SetValue(section, kvp.Value);
+ }
+ }
+
+ ///
+ /// Create a dictionary from the objects properties.
+ ///
+ /// Instance to convert
+ /// Dictionary with all properties (except SectionName)
+ /// section
+ public static IDictionary ToConfigDictionary(this IConfigurationSection section)
+ {
+ if (section == null) throw new ArgumentNullException("section");
+ var items = new Dictionary();
+ foreach (var propertyInfo in section.GetType().GetProperties())
+ {
+ if (propertyInfo.Name == "SectionName")
+ continue;
+
+ var value = propertyInfo.GetValue(section);
+ items[propertyInfo.Name] = string.Format(CultureInfo.InvariantCulture, "{0}", value);
+ }
+ return items;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Abstractions/Config/ConfigurationStore.cs b/src/Server/Coderr.Server.Abstractions/Config/ConfigurationStore.cs
new file mode 100644
index 00000000..33a4c889
--- /dev/null
+++ b/src/Server/Coderr.Server.Abstractions/Config/ConfigurationStore.cs
@@ -0,0 +1,29 @@
+using System;
+
+namespace Coderr.Server.Abstractions.Config
+{
+ ///
+ /// Used to modify configuration settings.
+ ///
+ ///
+ ///
+ /// Use dependency injection () to access the configuration.
+ ///
+ ///
+ public abstract class ConfigurationStore
+ {
+ ///
+ /// Load a settings section
+ ///
+ /// Type of section
+ /// Category if found; otherwise null.
+ public abstract T Load() where T : IConfigurationSection, new();
+
+ ///
+ /// Store a settings section.
+ ///
+ /// Category to persist.
+ /// section
+ public abstract void Store(IConfigurationSection section);
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Abstractions/Config/IConfiguration.cs b/src/Server/Coderr.Server.Abstractions/Config/IConfiguration.cs
new file mode 100644
index 00000000..6f4c4d82
--- /dev/null
+++ b/src/Server/Coderr.Server.Abstractions/Config/IConfiguration.cs
@@ -0,0 +1,9 @@
+namespace Coderr.Server.Abstractions.Config
+{
+ public interface IConfiguration where TConfigType : new()
+ {
+ TConfigType Value { get; }
+
+ void Save();
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Abstractions/Config/IConfigurationSection.cs b/src/Server/Coderr.Server.Abstractions/Config/IConfigurationSection.cs
new file mode 100644
index 00000000..b1097f96
--- /dev/null
+++ b/src/Server/Coderr.Server.Abstractions/Config/IConfigurationSection.cs
@@ -0,0 +1,17 @@
+using System.Collections.Generic;
+
+namespace Coderr.Server.Abstractions.Config
+{
+ ///
+ /// Purpose of this interface is to allow strongly types settings to be stored in a configuration store without
+ /// exposing magic strings.
+ ///
+ public interface IConfigurationSection
+ {
+ string SectionName { get; }
+
+ void Load(IDictionary settings);
+
+ IDictionary ToDictionary();
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Abstractions/HostConfig.cs b/src/Server/Coderr.Server.Abstractions/HostConfig.cs
new file mode 100644
index 00000000..f492439d
--- /dev/null
+++ b/src/Server/Coderr.Server.Abstractions/HostConfig.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Diagnostics;
+
+namespace Coderr.Server.Abstractions
+{
+ ///
+ /// Wraps either the configuration file or the Docker environment variables.
+ ///
+ public class HostConfig
+ {
+ public static HostConfig Instance = new HostConfig();
+
+ private static bool _isTriggered;
+
+ public bool IsRunningInDocker { get; set; }
+ public string ConnectionString { get; set; }
+
+ public bool IsDemo { get; set; } = Debugger.IsAttached;
+ public bool IsConfigured { get; private set; }
+
+ ///
+ /// Just to make it harder to take over an ongoing installation of Coderr on a public ip. Changed now and then.
+ ///
+ public string InstallationPassword { get; set; }
+
+ public event EventHandler Configured;
+
+ public override string ToString()
+ {
+ var tmp = IsRunningInDocker ? "[DOCKER] " : "[NATIVE] ";
+ return $"{tmp} running with {ConnectionString}";
+ }
+
+ ///
+ /// Mark configuration as complete.
+ ///
+ public void MarkAsConfigured()
+ {
+ IsConfigured = true;
+ }
+
+ ///
+ /// Separate method since it must be run after everyone have subscribed on the event.
+ ///
+ public void TriggeredConfigured()
+ {
+ if (_isTriggered) return;
+
+ _isTriggered = true;
+ IsConfigured = true;
+ Configured?.Invoke(this, EventArgs.Empty);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Abstractions/IConnectionFactory.cs b/src/Server/Coderr.Server.Abstractions/IConnectionFactory.cs
new file mode 100644
index 00000000..c97048c0
--- /dev/null
+++ b/src/Server/Coderr.Server.Abstractions/IConnectionFactory.cs
@@ -0,0 +1,11 @@
+using System.Data;
+using System.Security.Claims;
+
+namespace Coderr.Server.Abstractions
+{
+ public interface IConnectionFactory
+ {
+ IDbConnection OpenConnection(ClaimsPrincipal principal);
+
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Abstractions/IGotTransaction.cs b/src/Server/Coderr.Server.Abstractions/IGotTransaction.cs
new file mode 100644
index 00000000..299542b0
--- /dev/null
+++ b/src/Server/Coderr.Server.Abstractions/IGotTransaction.cs
@@ -0,0 +1,9 @@
+using System.Data.Common;
+
+namespace Coderr.Server.Abstractions
+{
+ public interface IGotTransaction
+ {
+ DbTransaction Transaction { get; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Abstractions/IPAddressExtension.cs b/src/Server/Coderr.Server.Abstractions/IPAddressExtension.cs
new file mode 100644
index 00000000..f82ee282
--- /dev/null
+++ b/src/Server/Coderr.Server.Abstractions/IPAddressExtension.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+using System.Net;
+using System.Text;
+
+namespace Coderr.Server.Abstractions
+{
+ ///
+ /// Extensions for IPAddress.
+ ///
+ public static class IpAddressExtensions
+ {
+ ///
+ /// An extension method to determine if an IP address is internal, as specified in RFC1918
+ ///
+ /// The IP address that will be tested
+ /// Returns true if the IP is internal, false if it is external
+ public static bool IsInternal(this IPAddress toTest)
+ {
+ if (IPAddress.IsLoopback(toTest)) return true;
+
+ if (toTest.IsIPv6LinkLocal || toTest.IsIPv6SiteLocal)
+ {
+ return true;
+ }
+
+ var bytes = toTest.GetAddressBytes();
+ switch (bytes[0])
+ {
+ case 10:
+ return true;
+ case 172:
+ return bytes[1] < 32 && bytes[1] >= 16;
+ case 192:
+ return bytes[1] == 168;
+ default:
+ return false;
+ }
+ }
+ }
+}
diff --git a/src/Server/Coderr.Server.Abstractions/Incidents/HighlightedContextDataProviderContext.cs b/src/Server/Coderr.Server.Abstractions/Incidents/HighlightedContextDataProviderContext.cs
new file mode 100644
index 00000000..cc43999d
--- /dev/null
+++ b/src/Server/Coderr.Server.Abstractions/Incidents/HighlightedContextDataProviderContext.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+using Coderr.Server.Api.Core.Incidents.Queries;
+
+namespace Coderr.Server.Abstractions.Incidents
+{
+ public class HighlightedContextDataProviderContext
+ {
+ private readonly IList _items;
+
+ public HighlightedContextDataProviderContext(IList items)
+ {
+ _items = items ?? throw new ArgumentNullException(nameof(items));
+ Tags = new string[0];
+ }
+
+ public int ApplicationId { get; set; }
+ public string Description { get; set; }
+
+ ///
+ /// Namespace + name of exception
+ ///
+ public string FullName { get; set; }
+
+ public int IncidentId { get; set; }
+
+ public IEnumerable Items => _items;
+
+ public string StackTrace { get; set; }
+ public string[] Tags { get; set; }
+
+ public void AddValue(HighlightedContextData contextData)
+ {
+ if (contextData == null) throw new ArgumentNullException(nameof(contextData));
+ _items.Add(contextData);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Abstractions/Incidents/IHighlightedContextDataProvider.cs b/src/Server/Coderr.Server.Abstractions/Incidents/IHighlightedContextDataProvider.cs
new file mode 100644
index 00000000..d7e7ee47
--- /dev/null
+++ b/src/Server/Coderr.Server.Abstractions/Incidents/IHighlightedContextDataProvider.cs
@@ -0,0 +1,11 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Coderr.Server.Api.Core.Incidents.Queries;
+
+namespace Coderr.Server.Abstractions.Incidents
+{
+ public interface IHighlightedContextDataProvider
+ {
+ Task CollectAsync(HighlightedContextDataProviderContext context);
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Abstractions/Incidents/IQuickfactProvider.cs b/src/Server/Coderr.Server.Abstractions/Incidents/IQuickfactProvider.cs
new file mode 100644
index 00000000..b3724fa1
--- /dev/null
+++ b/src/Server/Coderr.Server.Abstractions/Incidents/IQuickfactProvider.cs
@@ -0,0 +1,9 @@
+using System.Threading.Tasks;
+
+namespace Coderr.Server.Abstractions.Incidents
+{
+ public interface IQuickfactProvider
+ {
+ Task CollectAsync(QuickFactContext context);
+ }
+}
diff --git a/src/Server/Coderr.Server.Abstractions/Incidents/ISolutionProvider.cs b/src/Server/Coderr.Server.Abstractions/Incidents/ISolutionProvider.cs
new file mode 100644
index 00000000..00e2e0f6
--- /dev/null
+++ b/src/Server/Coderr.Server.Abstractions/Incidents/ISolutionProvider.cs
@@ -0,0 +1,14 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Coderr.Server.Api.Core.Incidents.Queries;
+
+namespace Coderr.Server.Abstractions.Incidents
+{
+ ///
+ /// Checks if there is a solution available for the current incident.
+ ///
+ public interface ISolutionProvider
+ {
+ Task SuggestSolutionAsync(SolutionProviderContext context);
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Abstractions/Incidents/QuickFactContext.cs b/src/Server/Coderr.Server.Abstractions/Incidents/QuickFactContext.cs
new file mode 100644
index 00000000..fa8812cb
--- /dev/null
+++ b/src/Server/Coderr.Server.Abstractions/Incidents/QuickFactContext.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using Coderr.Server.Api.Core.Incidents.Queries;
+
+namespace Coderr.Server.Abstractions.Incidents
+{
+ public class QuickFactContext
+ {
+ public QuickFactContext(int applicationId, int incidentId, ICollection facts)
+ {
+ if (applicationId <= 0) throw new ArgumentOutOfRangeException(nameof(applicationId));
+ if (incidentId <= 0) throw new ArgumentOutOfRangeException(nameof(incidentId));
+ ApplicationId = applicationId;
+ IncidentId = incidentId;
+ CollectedFacts = facts;
+ }
+ public int IncidentId { get; private set; }
+ public int ApplicationId { get; private set; }
+ public ICollection CollectedFacts { get; private set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Abstractions/Incidents/SolutionProviderContext.cs b/src/Server/Coderr.Server.Abstractions/Incidents/SolutionProviderContext.cs
new file mode 100644
index 00000000..f69a78df
--- /dev/null
+++ b/src/Server/Coderr.Server.Abstractions/Incidents/SolutionProviderContext.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using Coderr.Server.Api.Core.Incidents.Queries;
+
+namespace Coderr.Server.Abstractions.Incidents
+{
+ public class SolutionProviderContext
+ {
+ private readonly List _possibleSolutions;
+
+ public SolutionProviderContext(List possibleSolutions)
+ {
+ _possibleSolutions = possibleSolutions;
+ }
+
+ public int ApplicationId { get; set; }
+ public string Description { get; set; }
+
+ ///
+ /// Namespace + name of exception
+ ///
+ public string FullName { get; set; }
+
+ public int IncidentId { get; set; }
+
+ public string StackTrace { get; set; }
+ public string[] Tags { get; set; }
+
+ public void AddSuggestion(string suggestion, string motivation)
+ {
+ if (suggestion == null) throw new ArgumentNullException(nameof(suggestion));
+ if (motivation == null) throw new ArgumentNullException(nameof(motivation));
+ _possibleSolutions.Add(new SuggestedIncidentSolution {Reason = motivation, SuggestedSolution = suggestion});
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Abstractions/QueueConfig.cs b/src/Server/Coderr.Server.Abstractions/QueueConfig.cs
new file mode 100644
index 00000000..c1900f6e
--- /dev/null
+++ b/src/Server/Coderr.Server.Abstractions/QueueConfig.cs
@@ -0,0 +1,36 @@
+using System;
+using Coderr.Server.Abstractions.Boot;
+
+namespace Coderr.Server.Abstractions
+{
+ public class QueueConfig
+ {
+ public string ReportQueue { get; set; }
+ public string InboundPartitions { get; set; }
+ public string ReportEventQueue { get; set; }
+ public string AppQueue { get; set; }
+
+ public void Configure(IConfiguration config)
+ {
+ if (config == null)
+ {
+ throw new ArgumentNullException(nameof(config));
+ }
+
+ if (ServerConfig.Instance.IsLive)
+ {
+ ReportQueue = config.GetSection("MessageQueue")["ReportQueue"];
+ ReportEventQueue = config.GetSection("MessageQueue")["ReportEventQueue"];
+ AppQueue = config.GetSection("MessageQueue")["AppQueue"];
+ InboundPartitions = config.GetSection("MessageQueue")["InboundPartitions"];
+ }
+ else
+ {
+ ReportQueue = "ErrorReports";
+ ReportEventQueue = "ErrorReportEvents";
+ AppQueue = "Messaging";
+ InboundPartitions = "InboundPartitions";
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Abstractions/Reports/ReportConfig.cs b/src/Server/Coderr.Server.Abstractions/Reports/ReportConfig.cs
new file mode 100644
index 00000000..7a451f63
--- /dev/null
+++ b/src/Server/Coderr.Server.Abstractions/Reports/ReportConfig.cs
@@ -0,0 +1,73 @@
+using System.Collections.Generic;
+using Coderr.Server.Abstractions.Config;
+
+namespace Coderr.Server.Abstractions.Reports
+{
+ ///
+ /// Configuration settings for reports.
+ ///
+ public class ReportConfig : IConfigurationSection//, IReportConfig
+ {
+ ///
+ /// Creates a new instance of
+ ///
+ ///
+ ///
+ /// Sets default of MaxReportJsonSize to 2000000, MaxReportsPerIncident to 25 and RetentionDays to 90.
+ ///
+ ///
+ public ReportConfig()
+ {
+ MaxReportJsonSize = 2000000;
+ MaxReportsPerIncident = 25;
+ RetentionDays = 90;
+ }
+
+ ///
+ /// Maximum number of bytes that a uncompressed JSON report can be
+ ///
+ ///
+ ///
+ /// Used to filter out reports that are too large.
+ ///
+ ///
+ public int MaxReportJsonSize { get; set; }
+
+ ///
+ /// Max number of reports per incident
+ ///
+ ///
+ /// The oldest report(s) will be deleted if this limit is reached.
+ ///
+ public int MaxReportsPerIncident { get; set; }
+
+ ///
+ /// Number of days to store reports.
+ ///
+ ///
+ /// All reports older than this amount of days will be deleted.
+ ///
+ public int RetentionDays { get; set; }
+
+ ///
+ /// Number of days to store incidents that have not received any new reports.
+ ///
+ public int RetentionDaysIncidents { get; set; }
+
+ string IConfigurationSection.SectionName => "ReportConfig";
+
+ IDictionary IConfigurationSection.ToDictionary()
+ {
+ return this.ToConfigDictionary();
+ }
+
+ void IConfigurationSection.Load(IDictionary settings)
+ {
+ this.AssignProperties(settings);
+ if (MaxReportJsonSize == 0)
+ MaxReportJsonSize = 1000000;
+ if (RetentionDaysIncidents == 0)
+ RetentionDaysIncidents = 90;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Abstractions/Security/ClaimsExtensions.cs b/src/Server/Coderr.Server.Abstractions/Security/ClaimsExtensions.cs
new file mode 100644
index 00000000..8527dd08
--- /dev/null
+++ b/src/Server/Coderr.Server.Abstractions/Security/ClaimsExtensions.cs
@@ -0,0 +1,189 @@
+using System;
+using System.Security.Authentication;
+using System.Security.Claims;
+using System.Security.Principal;
+
+namespace Coderr.Server.Abstractions.Security
+{
+ ///
+ /// Our Coderr specific extensions for claims handling.
+ ///
+ public static class ClaimsExtensions
+ {
+ ///
+ /// Throws if returns false.
+ ///
+ /// principal to search in
+ /// application to check
+ /// true if the claim was found with the given value; otherwise false.
+ /// Claim is not found in the identity.
+ public static void EnsureApplicationAdmin(this ClaimsPrincipal principal, int applicationId)
+ {
+ if (!IsApplicationAdmin(principal, applicationId))
+ throw new UnauthorizedAccessException(
+ $"User {principal.Identity.Name} is not authorized to manage application {applicationId}.");
+ }
+
+ ///
+ /// Get account id ().
+ ///
+ /// principal to search in
+ /// id
+ /// Claim is not found in the identity/ies.
+ public static int GetAccountId(this ClaimsPrincipal principal)
+ {
+ var claim = principal.FindFirst(x => x.Type == ClaimTypes.NameIdentifier);
+ if (claim == null)
+ throw new InvalidOperationException(
+ "Failed to find ClaimTypes.NameIdentifier, user is probably not logged in.");
+
+ if (int.TryParse(claim.Value, out var userId)) return userId;
+
+ var ex = new FormatException($"UserId {claim.Value} is not a number.");
+ foreach (var c in principal.Claims)
+ {
+ ex.Data[$"Claim.{c.Type}"] = c.Value;
+ }
+
+ throw ex;
+ }
+
+ ///
+ /// Get account id ().
+ ///
+ /// principal to search in
+ /// id
+ /// Claim is not found in the identity/ies.
+ public static int FindAccountId(this ClaimsPrincipal principal)
+ {
+ var claim = principal.FindFirst(x => x.Type == ClaimTypes.NameIdentifier);
+ if (claim == null)
+ return 0;
+
+ if (int.TryParse(claim.Value, out var userId))
+ return userId;
+
+ return -1;
+ }
+
+ ///
+ /// Get account id ().
+ ///
+ /// principal to search in
+ /// id
+ /// Claim is not found in the identity/ies.
+ public static int GetAccountId(this IPrincipal principal)
+ {
+ var prince = principal as ClaimsPrincipal;
+ if (prince == null)
+ throw new AuthenticationException(principal + " is not a ClaimsPrincipal.");
+
+ var claim = prince.FindFirst(x => x.Type == ClaimTypes.NameIdentifier);
+ if (claim == null)
+ throw new InvalidOperationException(
+ "Failed to find ClaimTypes.NameIdentifier, user is probably not logged in.");
+
+ return int.Parse(claim.Value);
+ }
+
+ ///
+ /// Get account id ().
+ ///
+ /// identity to search in
+ /// id
+ /// Claim is not found in the identity.
+ public static int GetAccountId(this ClaimsIdentity identity)
+ {
+ var claim = identity.FindFirst(x => x.Type == ClaimTypes.NameIdentifier);
+ if (claim == null)
+ throw new InvalidOperationException(
+ "Failed to find ClaimTypes.NameIdentifier, user is probably not logged in.");
+
+ return int.Parse(claim.Value);
+ }
+
+ ///
+ /// Checks if the currently logged in user is the same as the given id.
+ ///
+ /// Some kind of principal
+ /// AccountId to compare with.
+ ///
+ /// true if current principal is a ClaimsPrincipal, the user is authenticated and the accountId is
+ /// same; otherwise false.
+ ///
+ public static bool IsCurrentAccount(this IPrincipal principal, int accountId)
+ {
+ var p = principal as ClaimsPrincipal;
+ if (p == null)
+ return false;
+
+ if (!p.Identity.IsAuthenticated)
+ return false;
+
+ return accountId == p.GetAccountId();
+ }
+
+ ///
+ /// Checks if the user has the CoderrClaims.ApplicationAdmin claim or if user is SysAdmin or System.
+ ///
+ /// principal to search in
+ /// Application to check
+ /// true if the claim was found with the given value; otherwise false.
+ /// Claim is not found in the identity.
+ public static bool IsApplicationAdmin(this ClaimsPrincipal principal, int applicationId)
+ {
+ return principal.HasClaim(CoderrClaims.ApplicationAdmin, applicationId.ToString())
+ || principal.IsInRole(CoderrRoles.SysAdmin)
+ || principal.IsInRole(CoderrRoles.System);
+ }
+
+ ///
+ /// Get if the CoderrClaims.Application claim is specified for the given application (claim value)
+ ///
+ /// principal to search in
+ /// App to check
+ /// Check if user is in role SysAdmin or if the user is the System.
+ /// true if the claim was found with the given value; otherwise false.
+ /// Claim is not found in the identity.
+ public static bool IsApplicationMember(this ClaimsPrincipal principal, int applicationId, bool checkSystemRoles = false)
+ {
+ var isAdmin = principal.HasClaim(CoderrClaims.Application, applicationId.ToString());
+ if (checkSystemRoles)
+ isAdmin = isAdmin || IsSysAdmin(principal) || principal.IsInRole(CoderrRoles.System);
+ return isAdmin;
+ }
+
+ ///
+ /// Get if the user is part of CoderrRoles.SysAdmin.
+ ///
+ /// principal to search in
+ /// true if the role was found; otherwise false.
+ public static bool IsSysAdmin(this IPrincipal principal)
+ {
+ return principal.IsInRole(CoderrRoles.SysAdmin);
+ }
+
+ public static string ToFriendlyString(this IPrincipal principal)
+ {
+ var cc = principal as ClaimsPrincipal;
+ if (cc == null || principal.Identity?.IsAuthenticated != true)
+ {
+ return "Anonymous";
+ }
+
+ string str = cc.Identity.Name + " Claims[";
+ foreach (var claim in cc.Claims)
+ {
+ var pos = claim.Type.LastIndexOf('/');
+ if (pos != -1)
+ str += claim.Type.Substring(pos + 1);
+ else
+ str += claim.Type;
+
+ str += "=" + claim.Value + ", ";
+ }
+ str = str.Remove(str.Length - 2, 2) + "]";
+ return str;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Abstractions/Security/CoderrClaims.cs b/src/Server/Coderr.Server.Abstractions/Security/CoderrClaims.cs
new file mode 100644
index 00000000..5194afe3
--- /dev/null
+++ b/src/Server/Coderr.Server.Abstractions/Security/CoderrClaims.cs
@@ -0,0 +1,17 @@
+using System.Security.Claims;
+
+namespace Coderr.Server.Abstractions.Security
+{
+ public class CoderrClaims
+ {
+ public const string Application = "http://coderr/claims/application";
+ public const string ApplicationAdmin = "http://coderr/claims/application/admin";
+
+ public static readonly ClaimsPrincipal SystemPrincipal = new ClaimsPrincipal(new ClaimsIdentity(new[]
+ {
+ new Claim(ClaimTypes.NameIdentifier, "0"),
+ new Claim(ClaimTypes.Name, "System"),
+ new Claim(ClaimTypes.Role, CoderrRoles.System)
+ }));
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Abstractions/Security/CoderrRoles.cs b/src/Server/Coderr.Server.Abstractions/Security/CoderrRoles.cs
new file mode 100644
index 00000000..7478c090
--- /dev/null
+++ b/src/Server/Coderr.Server.Abstractions/Security/CoderrRoles.cs
@@ -0,0 +1,9 @@
+namespace Coderr.Server.Abstractions.Security
+{
+ public class CoderrRoles
+ {
+ public const string SysAdmin = "SysAdmin";
+ public const string User = "User";
+ public const string System = "System";
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Abstractions/Security/IPrincipalAccessor.cs b/src/Server/Coderr.Server.Abstractions/Security/IPrincipalAccessor.cs
new file mode 100644
index 00000000..26499018
--- /dev/null
+++ b/src/Server/Coderr.Server.Abstractions/Security/IPrincipalAccessor.cs
@@ -0,0 +1,14 @@
+using System.Security.Claims;
+
+namespace Coderr.Server.Abstractions.Security
+{
+ ///
+ /// Used to move principal from the queue to the current container scope so that a proper DB connection can be opened.
+ ///
+ public interface IPrincipalAccessor
+ {
+ ClaimsPrincipal Principal { get; set; }
+
+ ClaimsPrincipal FindPrincipal();
+ }
+}
diff --git a/src/Server/Coderr.Server.Abstractions/ServerConfig.cs b/src/Server/Coderr.Server.Abstractions/ServerConfig.cs
new file mode 100644
index 00000000..4a974dd3
--- /dev/null
+++ b/src/Server/Coderr.Server.Abstractions/ServerConfig.cs
@@ -0,0 +1,47 @@
+using System;
+
+namespace Coderr.Server.Abstractions
+{
+ public class ServerConfig
+ {
+ public const string Premise = "Premise";
+ public const string Live = "Live";
+
+ public static ServerConfig Instance = new ServerConfig();
+ private ServerType _serverType;
+
+ public bool IsLive { get; private set; }
+
+ public bool UseSmtpHandler { get; set; }
+
+ public ServerType ServerType
+ {
+ get => _serverType;
+ set
+ {
+ _serverType = value;
+ IsLive = value == ServerType.Live;
+ UseSmtpHandler = !IsLive;
+ }
+ }
+
+ public QueueConfig Queues { get; set; } = new QueueConfig();
+ public bool IsCommercial { get; set; }
+
+ public bool IsModuleIgnored(Type type)
+ {
+ if (Instance.IsLive)
+ {
+ if (type.Assembly.GetName().Name.Contains($".{ServerConfig.Premise}"))
+ return true;
+ }
+ else
+ {
+ if (type.Assembly.GetName().Name.Contains($".{ServerConfig.Live}"))
+ return true;
+ }
+
+ return false;
+ }
+ }
+}
diff --git a/src/Server/Coderr.Server.Abstractions/ServerType.cs b/src/Server/Coderr.Server.Abstractions/ServerType.cs
new file mode 100644
index 00000000..3fb41169
--- /dev/null
+++ b/src/Server/Coderr.Server.Abstractions/ServerType.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace Coderr.Server.Abstractions
+{
+ [Flags]
+ public enum ServerType
+ {
+ Community = 0,
+ Premise = 1,
+ PremisePlus = 3,
+ Live = 4
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api.Client.Tests/Coderr.Server.Api.Client.Tests.csproj b/src/Server/Coderr.Server.Api.Client.Tests/Coderr.Server.Api.Client.Tests.csproj
new file mode 100644
index 00000000..b14c5c9f
--- /dev/null
+++ b/src/Server/Coderr.Server.Api.Client.Tests/Coderr.Server.Api.Client.Tests.csproj
@@ -0,0 +1,29 @@
+
+
+ netcoreapp3.1
+ Coderr.Server.Api.Client.Tests
+ Coderr.Server.Api.Client.Tests
+ Debug;Release;Premise
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api.Client.Tests/TryTheClient.cs b/src/Server/Coderr.Server.Api.Client.Tests/TryTheClient.cs
new file mode 100644
index 00000000..b9b7bf2c
--- /dev/null
+++ b/src/Server/Coderr.Server.Api.Client.Tests/TryTheClient.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Net;
+using System.Threading.Tasks;
+using Coderr.Server.Api.Core.Accounts.Queries;
+using FluentAssertions;
+
+namespace Coderr.Server.Api.Client.Tests
+{
+#if DEBUG
+ public class TryTheClient
+ {
+ //[Fact]
+ public async Task Test()
+ {
+ var client = new ServerApiClient();
+ client.Open(new Uri("http://localhost/coderr/"), "", "");
+ FindAccountByUserNameResult result = null;
+ try
+ {
+ result = await client.QueryAsync(new FindAccountByUserName("admin"));
+ }
+ catch (WebException)
+ {
+ }
+
+
+ result.Should().NotBeNull();
+ }
+ }
+#endif
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api.Client/Coderr.Server.Api.Client.csproj b/src/Server/Coderr.Server.Api.Client/Coderr.Server.Api.Client.csproj
new file mode 100644
index 00000000..83788da5
--- /dev/null
+++ b/src/Server/Coderr.Server.Api.Client/Coderr.Server.Api.Client.csproj
@@ -0,0 +1,41 @@
+
+
+ netstandard2.0
+ 2.1.5
+ true
+ bin\$(Configuration)\$(TargetFramework)\Coderr.Server.Api.Client.xml
+ Debug;Release;Premise
+
+
+ Coderr.Server.ApiClient
+ 1TCompany AB
+ API client for Coderr Server.
+ true
+ Switched to HttpClient
+ Copyright 2019 © 1TCompany AB. All rights reserved.
+ logger exceptions analysis .net-core netstandard
+ https://coderr.io/images/nuget_icon.png
+ https://github.com/coderrio/coderr.server
+ git
+ Apache-2.0
+ https://coderr.io
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Server/Coderr.Server.Api.Client/Json/IncludeNonPublicMembersContractResolver.cs b/src/Server/Coderr.Server.Api.Client/Json/IncludeNonPublicMembersContractResolver.cs
new file mode 100644
index 00000000..430a91d5
--- /dev/null
+++ b/src/Server/Coderr.Server.Api.Client/Json/IncludeNonPublicMembersContractResolver.cs
@@ -0,0 +1,37 @@
+using System.Reflection;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Serialization;
+
+namespace Coderr.Server.Api.Client.Json
+{
+ ///
+ /// Used by JSON.NET to be able to deserialize properties with private setters.
+ ///
+ public class IncludeNonPublicAndUseCamelCaseContractResolver : CamelCasePropertyNamesContractResolver
+ {
+ //protected override List GetSerializableMembers(Type objectType)
+ //{
+ // var members = base.GetSerializableMembers(objectType);
+ // return members.Where(m => !m.Name.EndsWith("k__BackingField")).ToList();
+ //}
+
+ ///
+ protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
+ {
+ //TODO: Maybe cache
+ var prop = base.CreateProperty(member, memberSerialization);
+
+ if (!prop.Writable)
+ {
+ var property = member as PropertyInfo;
+ if (property != null)
+ {
+ var hasPrivateSetter = property.GetSetMethod(true) != null;
+ prop.Writable = hasPrivateSetter;
+ }
+ }
+
+ return prop;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api.Client/ServerApiClient.cs b/src/Server/Coderr.Server.Api.Client/ServerApiClient.cs
new file mode 100644
index 00000000..85e97c9d
--- /dev/null
+++ b/src/Server/Coderr.Server.Api.Client/ServerApiClient.cs
@@ -0,0 +1,143 @@
+using System;
+using System.Net;
+using System.Net.Http;
+using System.Security.Claims;
+using System.Security.Cryptography;
+using System.Text;
+using System.Threading.Tasks;
+using Coderr.Server.Api.Client.Json;
+using DotNetCqs;
+using Newtonsoft.Json;
+
+namespace Coderr.Server.Api.Client
+{
+ ///
+ /// Client for the Coderr server API
+ ///
+ public class ServerApiClient : IMessageBus, IQueryBus
+ {
+ private readonly JsonSerializerSettings _jsonSerializerSettings = new JsonSerializerSettings
+ {
+ ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor,
+ Formatting = Formatting.Indented,
+ NullValueHandling = NullValueHandling.Ignore,
+ ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
+ ContractResolver = new IncludeNonPublicAndUseCamelCaseContractResolver()
+ };
+
+ private string _apiKey;
+ private string _sharedSecret;
+ private Uri _uri;
+
+
+ ///
+ /// Send a query to the server.
+ ///
+ /// Principal for the user making the request
+ /// Message being sent
+ /// task
+ async Task IMessageBus.SendAsync(ClaimsPrincipal principal, object message)
+ {
+ await RequestAsync(HttpMethod.Post, "send", message);
+ }
+
+ async Task IMessageBus.SendAsync(ClaimsPrincipal principal, Message message)
+ {
+ await RequestAsync(HttpMethod.Post, "send", message.Body);
+ }
+
+ async Task IMessageBus.SendAsync(Message message)
+ {
+ await RequestAsync(HttpMethod.Post, "send", message.Body);
+ }
+
+ ///
+ /// Send a command or event
+ ///
+ /// message
+ /// task
+ public async Task SendAsync(object message)
+ {
+ await RequestAsync(HttpMethod.Post, "send", message);
+ }
+
+ async Task IQueryBus.QueryAsync(ClaimsPrincipal user, Query query)
+ {
+ //TODO: Unwrap the cqs object to query parameters instead
+ //to allow caching in the server
+ var response = await RequestAsync(HttpMethod.Post, "query", query);
+ if (response.StatusCode == HttpStatusCode.NotFound)
+ return default(TResult);
+ return await DeserializeResponse(response.Content);
+ }
+
+ ///
+ /// Make a query
+ ///
+ /// Type of result that the query returns
+ /// query to invoke
+ /// task
+ public async Task QueryAsync(Query query)
+ {
+ //TODO: Unwrap the cqs object to query parameters instead
+ //to allow caching in the server
+ var response = await RequestAsync(HttpMethod.Post, "query", query);
+ if (response.StatusCode == HttpStatusCode.NotFound)
+ return default(TResult);
+ response.EnsureSuccessStatusCode();
+ return await DeserializeResponse(response.Content);
+ }
+
+
+ ///
+ /// Open a channel
+ ///
+ /// Root URL to the Coderr web
+ /// API key from the administration area in Coderr web
+ /// Shared secret from the administration area in Coderr web
+ public void Open(Uri uri, string apiKey, string sharedSecret)
+ {
+ _apiKey = apiKey ?? throw new ArgumentNullException(nameof(apiKey));
+ _sharedSecret = sharedSecret ?? throw new ArgumentNullException(nameof(sharedSecret));
+ _uri = uri ?? throw new ArgumentNullException(nameof(uri));
+ }
+
+
+ private async Task DeserializeResponse(HttpContent content)
+ {
+ var jsonStr = await content.ReadAsStringAsync();
+ try
+ {
+ var responseObj = JsonConvert.DeserializeObject(jsonStr, typeof(TResult), _jsonSerializerSettings);
+ return (TResult) responseObj;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException("Failed to deserialize " + jsonStr, ex);
+ }
+ }
+
+ private async Task RequestAsync(HttpMethod httpMethod, string cqsType, object cqsObject)
+ {
+ var request = new HttpRequestMessage(httpMethod, $"{_uri}api/cqs");
+ request.Headers.Add("X-Api-Key", _apiKey);
+ request.Headers.Add("X-Cqs-Name", cqsObject.GetType().Name);
+
+ var json = JsonConvert.SerializeObject(cqsObject, _jsonSerializerSettings);
+ var buffer = Encoding.UTF8.GetBytes(json);
+ var hamc = new HMACSHA256(Encoding.UTF8.GetBytes(_sharedSecret.ToLower()));
+ var hash = hamc.ComputeHash(buffer);
+ var signature = Convert.ToBase64String(hash);
+ request.Headers.Add("Authorization", "ApiKey " + _apiKey + " " + signature);
+ request.Headers.Add("X-Api-Signature", signature);
+
+ request.Content = new ByteArrayContent(buffer);
+
+ var client = new HttpClient();
+ var response = await client.SendAsync(request);
+ if ((int)response.StatusCode >= 500)
+ throw new HttpRequestException(response.ReasonPhrase);
+ return response;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api.Client/StringBuilderExtensions.cs b/src/Server/Coderr.Server.Api.Client/StringBuilderExtensions.cs
similarity index 92%
rename from src/Server/OneTrueError.Api.Client/StringBuilderExtensions.cs
rename to src/Server/Coderr.Server.Api.Client/StringBuilderExtensions.cs
index 40eb8b9c..d201b06b 100644
--- a/src/Server/OneTrueError.Api.Client/StringBuilderExtensions.cs
+++ b/src/Server/Coderr.Server.Api.Client/StringBuilderExtensions.cs
@@ -1,7 +1,7 @@
using System;
using System.Text;
-namespace OneTrueError.Api.Client
+namespace Coderr.Server.Api.Client
{
internal static class StringBuilderExtensions
{
diff --git a/src/Server/OneTrueError.Api/AuthorizeAttribute.cs b/src/Server/Coderr.Server.Api/AuthorizeAttribute.cs
similarity index 89%
rename from src/Server/OneTrueError.Api/AuthorizeAttribute.cs
rename to src/Server/Coderr.Server.Api/AuthorizeAttribute.cs
index 8c9d50e7..548216ae 100644
--- a/src/Server/OneTrueError.Api/AuthorizeAttribute.cs
+++ b/src/Server/Coderr.Server.Api/AuthorizeAttribute.cs
@@ -1,27 +1,26 @@
-using System;
-using OneTrueError.Api.Core;
-
-namespace OneTrueError.Api
-{
- ///
- /// Authorize on specific roles.
- ///
- [AttributeUsage(AttributeTargets.Class), IgnoreField]
- public class AuthorizeRolesAttribute : Attribute
- {
- ///
- /// Creates a new instance of .
- ///
- /// roles granted access
- public AuthorizeRolesAttribute(params string[] roles)
- {
- if (roles == null) throw new ArgumentNullException("roles");
- Roles = roles;
- }
-
- ///
- /// Roles granted access
- ///
- public string[] Roles { get; private set; }
- }
+using System;
+
+namespace Coderr.Server.Api
+{
+ ///
+ /// Authorize on specific roles.
+ ///
+ [AttributeUsage(AttributeTargets.Class), IgnoreField]
+ public class AuthorizeRolesAttribute : Attribute
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// roles granted access
+ public AuthorizeRolesAttribute(params string[] roles)
+ {
+ if (roles == null) throw new ArgumentNullException("roles");
+ Roles = roles;
+ }
+
+ ///
+ /// Roles granted access
+ ///
+ public string[] Roles { get; private set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Coderr.Server.Api.csproj b/src/Server/Coderr.Server.Api/Coderr.Server.Api.csproj
new file mode 100644
index 00000000..c9de5edd
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Coderr.Server.Api.csproj
@@ -0,0 +1,31 @@
+
+
+ netstandard2.0
+ 2.1.5
+ bin\$(Configuration)\$(TargetFramework)\Coderr.Server.Api.xml
+ Added the whitelist API
+
+
+ Coderr.Server.Api
+ Coderr.Server.Api
+ true
+ Coderr.Server.Api
+ Coderr AB
+ API definition for Coderr Server.
+ true
+ Copyright 2020 © Coderr AB. All rights reserved.
+ logger exceptions analysis .net-core netstandard
+ https://coderr.io/images/nuget_icon.png
+ https://github.com/coderrio/coderr.server
+ git
+ Apache-2.0
+ https://coderr.io
+
+
+ 1701;1702;1705;1591
+
+
+
+
+
+
diff --git a/src/Server/Coderr.Server.Api/CommandAttribute.cs b/src/Server/Coderr.Server.Api/CommandAttribute.cs
new file mode 100644
index 00000000..651b697e
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/CommandAttribute.cs
@@ -0,0 +1,10 @@
+namespace Coderr.Server.Api
+{
+ ///
+ /// Marker attribute to tell which DTOs are commands
+ ///
+ public class CommandAttribute : MessageAttribute
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Accounts/Commands/DeclineInvitation.cs b/src/Server/Coderr.Server.Api/Core/Accounts/Commands/DeclineInvitation.cs
similarity index 86%
rename from src/Server/OneTrueError.Api/Core/Accounts/Commands/DeclineInvitation.cs
rename to src/Server/Coderr.Server.Api/Core/Accounts/Commands/DeclineInvitation.cs
index c63a0cd4..244ae214 100644
--- a/src/Server/OneTrueError.Api/Core/Accounts/Commands/DeclineInvitation.cs
+++ b/src/Server/Coderr.Server.Api/Core/Accounts/Commands/DeclineInvitation.cs
@@ -1,34 +1,34 @@
-using System;
-using DotNetCqs;
-
-namespace OneTrueError.Api.Core.Accounts.Commands
-{
- ///
- /// Invited person do not want to accept the invitation
- ///
- public class DeclineInvitation : Command
- {
- ///
- /// Serialization constructor
- ///
- protected DeclineInvitation()
- {
- }
-
- ///
- /// Creates a new instance of .
- ///
- /// invitation key (typically a guid)
- public DeclineInvitation(string invitationId)
- {
- if (string.IsNullOrEmpty(invitationId))
- throw new ArgumentException("Argument is null or empty", "invitationId");
- InvitationId = invitationId;
- }
-
- ///
- /// Invitation key (typically a guid)
- ///
- public string InvitationId { get; private set; }
- }
+using System;
+
+namespace Coderr.Server.Api.Core.Accounts.Commands
+{
+ ///
+ /// Invited person do not want to accept the invitation
+ ///
+ [Message]
+ public class DeclineInvitation
+ {
+ ///
+ /// Serialization constructor
+ ///
+ protected DeclineInvitation()
+ {
+ }
+
+ ///
+ /// Creates a new instance of .
+ ///
+ /// invitation key (typically a guid)
+ public DeclineInvitation(string invitationId)
+ {
+ if (string.IsNullOrEmpty(invitationId))
+ throw new ArgumentException("Argument is null or empty", "invitationId");
+ InvitationId = invitationId;
+ }
+
+ ///
+ /// Invitation key (typically a guid)
+ ///
+ public string InvitationId { get; private set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Accounts/Commands/RegisterAccount.cs b/src/Server/Coderr.Server.Api/Core/Accounts/Commands/RegisterAccount.cs
new file mode 100644
index 00000000..4afce887
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Accounts/Commands/RegisterAccount.cs
@@ -0,0 +1,86 @@
+using System;
+
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Local
+
+namespace Coderr.Server.Api.Core.Accounts.Commands
+{
+ ///
+ /// Register a new account and send out an activation email.
+ ///
+ [Message]
+ public class RegisterAccount
+ {
+ ///
+ /// Creates a new instance of
+ ///
+ /// User name
+ /// Password as entered by the user
+ /// Email address
+ public RegisterAccount(string userName, string password, string email)
+ {
+ UserName = userName ?? throw new ArgumentNullException("userName");
+ Password = password ?? throw new ArgumentNullException("password");
+ Email = email ?? throw new ArgumentNullException("email");
+ }
+
+ ///
+ /// Serialization constructor.
+ ///
+ protected RegisterAccount()
+ {
+ }
+
+ ///
+ /// Use a specific account id
+ ///
+ ///
+ /// 0 = auto increment
+ ///
+ public int AccountId { get; private set; }
+
+ ///
+ /// do not send an activation email, activate the account directly.
+ ///
+ public bool ActivateDirectly { get; private set; }
+
+ ///
+ /// Email address.
+ ///
+ public string Email { get; private set; }
+
+ ///
+ /// Password as entered by the user.
+ ///
+ public string Password { get; private set; }
+
+ ///
+ /// User name
+ ///
+ public string UserName { get; private set; }
+
+ ///
+ /// The the registration was due to an invitation, we need to redirect back to that invite.
+ ///
+ public string ReturnUrl { get; set; }
+
+ ///
+ /// Activate this account directly
+ ///
+ /// Id of the account
+ public void Activate(int accountId)
+ {
+ if (accountId <= 0) throw new ArgumentOutOfRangeException("accountId");
+ ActivateDirectly = true;
+ AccountId = accountId;
+ }
+
+ ///
+ /// Activate this account directly
+ ///
+ public void Activate()
+ {
+ ActivateDirectly = true;
+ AccountId = 0;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Accounts/Commands/RequestPasswordReset.cs b/src/Server/Coderr.Server.Api/Core/Accounts/Commands/RequestPasswordReset.cs
new file mode 100644
index 00000000..1292b360
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Accounts/Commands/RequestPasswordReset.cs
@@ -0,0 +1,33 @@
+using System;
+
+namespace Coderr.Server.Api.Core.Accounts.Commands
+{
+ ///
+ /// Request a password reset (i.e. lock account, email an activation link to the user and wait for activation).
+ ///
+ [Message]
+ public class RequestPasswordReset
+ {
+ ///
+ /// Serialization constructor
+ ///
+ protected RequestPasswordReset()
+ {
+ }
+
+ ///
+ /// Create a new instance of .
+ ///
+ /// Email address associated with the user account.
+ public RequestPasswordReset(string emailAddress)
+ {
+ if (emailAddress == null) throw new ArgumentNullException("emailAddress");
+ EmailAddress = emailAddress;
+ }
+
+ ///
+ /// Email address associated with the user account.
+ ///
+ public string EmailAddress { get; private set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Accounts/Events/AccountActivated.cs b/src/Server/Coderr.Server.Api/Core/Accounts/Events/AccountActivated.cs
similarity index 83%
rename from src/Server/OneTrueError.Api/Core/Accounts/Events/AccountActivated.cs
rename to src/Server/Coderr.Server.Api/Core/Accounts/Events/AccountActivated.cs
index b2a4f8d2..0852358b 100644
--- a/src/Server/OneTrueError.Api/Core/Accounts/Events/AccountActivated.cs
+++ b/src/Server/Coderr.Server.Api/Core/Accounts/Events/AccountActivated.cs
@@ -1,46 +1,46 @@
-using System;
-using DotNetCqs;
-
-namespace OneTrueError.Api.Core.Accounts.Events
-{
- ///
- /// Published when the user have clicked on the activation link in the registration email.
- ///
- public class AccountActivated : ApplicationEvent
- {
- ///
- /// Creates a new instance of -
- ///
- /// Primary key for the created account
- /// username that the account was created with.
- public AccountActivated(int accountId, string userName)
- {
- if (userName == null) throw new ArgumentNullException("userName");
- if (accountId <= 0) throw new ArgumentOutOfRangeException("accountId");
- AccountId = accountId;
- UserName = userName;
- }
-
- ///
- /// Serialization constructor.
- ///
- protected AccountActivated()
- {
- }
-
- ///
- /// Primary key for the account
- ///
- public int AccountId { get; set; }
-
- ///
- /// Email address associated with the account.
- ///
- public string EmailAddress { get; set; }
-
- ///
- /// Unique user name
- ///
- public string UserName { get; set; }
- }
+using System;
+
+namespace Coderr.Server.Api.Core.Accounts.Events
+{
+ ///
+ /// Published when the user have clicked on the activation link in the registration email.
+ ///
+ [Message]
+ public class AccountActivated
+ {
+ ///
+ /// Creates a new instance of -
+ ///
+ /// Primary key for the created account
+ /// user name that the account was created with.
+ public AccountActivated(int accountId, string userName)
+ {
+ if (userName == null) throw new ArgumentNullException("userName");
+ if (accountId <= 0) throw new ArgumentOutOfRangeException("accountId");
+ AccountId = accountId;
+ UserName = userName;
+ }
+
+ ///
+ /// Serialization constructor.
+ ///
+ protected AccountActivated()
+ {
+ }
+
+ ///
+ /// Primary key for the account
+ ///
+ public int AccountId { get; set; }
+
+ ///
+ /// Email address associated with the account.
+ ///
+ public string EmailAddress { get; set; }
+
+ ///
+ /// Unique user name
+ ///
+ public string UserName { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Accounts/Events/AccountRegistered.cs b/src/Server/Coderr.Server.Api/Core/Accounts/Events/AccountRegistered.cs
new file mode 100644
index 00000000..ab78462e
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Accounts/Events/AccountRegistered.cs
@@ -0,0 +1,54 @@
+using System;
+
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Local
+
+namespace Coderr.Server.Api.Core.Accounts.Events
+{
+ ///
+ /// An user have registered an account and activated it.
+ ///
+ [Message]
+ public class AccountRegistered
+ {
+ ///
+ /// Create a new instance of -
+ ///
+ /// Account id (primary key).
+ /// User name as entered by the user.
+ public AccountRegistered(int accountId, string userName)
+ {
+ if (accountId <= 0) throw new ArgumentNullException("accountId");
+ AccountId = accountId;
+ UserName = userName ?? throw new ArgumentNullException(nameof(userName));
+ }
+
+ ///
+ /// Serialization constructor
+ ///
+ protected AccountRegistered()
+ {
+ }
+
+ ///
+ /// Account id (primary key).
+ ///
+
+ public int AccountId { get; private set; }
+
+ ///
+ /// The registered user is a system administrator
+ ///
+ ///
+ ///
+ /// System administrators can create new applications, decide who is application administrator
+ /// and configure other system wide settings.
+ ///
+ ///
+ public bool IsSysAdmin { get; set; }
+
+ ///
+ /// User name as entered by the user.
+ ///
+ public string UserName { get; private set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Accounts/Events/InvitationAccepted.cs b/src/Server/Coderr.Server.Api/Core/Accounts/Events/InvitationAccepted.cs
similarity index 89%
rename from src/Server/OneTrueError.Api/Core/Accounts/Events/InvitationAccepted.cs
rename to src/Server/Coderr.Server.Api/Core/Accounts/Events/InvitationAccepted.cs
index a64d7067..1d0ddb26 100644
--- a/src/Server/OneTrueError.Api/Core/Accounts/Events/InvitationAccepted.cs
+++ b/src/Server/Coderr.Server.Api/Core/Accounts/Events/InvitationAccepted.cs
@@ -1,66 +1,66 @@
-using System;
-using DotNetCqs;
-
-namespace OneTrueError.Api.Core.Accounts.Events
-{
- ///
- /// A user have accepted an invitation.
- ///
- public class InvitationAccepted : ApplicationEvent
- {
- ///
- /// Creates a new instance of .
- ///
- /// account that accepted the inviation
- /// user that made the invite
- /// userName of the person that accepted the invitation
- /// invitedByUserName; userName
- /// accountId
- public InvitationAccepted(int accountId, string invitedByUserName, string userName)
- {
- if (invitedByUserName == null) throw new ArgumentNullException("invitedByUserName");
- if (userName == null) throw new ArgumentNullException("userName");
- if (accountId <= 0) throw new ArgumentOutOfRangeException("accountId");
- AccountId = accountId;
- InvitedByUserName = invitedByUserName;
- UserName = userName;
- }
-
- ///
- /// Serialization constructor.
- ///
- protected InvitationAccepted()
- {
- }
-
- ///
- /// The email that the inviation was accepted by.
- ///
- public string AcceptedEmailAddress { get; set; }
-
- ///
- /// Id of the user that accepted the invitation
- ///
- public int AccountId { get; set; }
-
- ///
- /// Applications that the user got access to.
- ///
- public int[] ApplicationIds { get; set; }
-
- ///
- /// User that created the invite.
- ///
- public string InvitedByUserName { get; set; }
-
- ///
- /// Email address that the invitation was sent to.
- ///
- public string InvitedEmailAddress { get; set; }
-
- ///
- /// The user that accepted the invitation
- ///
- public string UserName { get; set; }
- }
+using System;
+
+namespace Coderr.Server.Api.Core.Accounts.Events
+{
+ ///
+ /// A user have accepted an invitation.
+ ///
+ [Message]
+ public class InvitationAccepted
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// account that accepted the invitation
+ /// user that made the invite
+ /// userName of the person that accepted the invitation
+ /// invitedByUserName; userName
+ /// accountId
+ public InvitationAccepted(int accountId, string invitedByUserName, string userName)
+ {
+ if (invitedByUserName == null) throw new ArgumentNullException("invitedByUserName");
+ if (userName == null) throw new ArgumentNullException("userName");
+ if (accountId <= 0) throw new ArgumentOutOfRangeException("accountId");
+ AccountId = accountId;
+ InvitedByUserName = invitedByUserName;
+ UserName = userName;
+ }
+
+ ///
+ /// Serialization constructor.
+ ///
+ protected InvitationAccepted()
+ {
+ }
+
+ ///
+ /// The email that the invitation was accepted by.
+ ///
+ public string AcceptedEmailAddress { get; set; }
+
+ ///
+ /// Id of the user that accepted the invitation
+ ///
+ public int AccountId { get; set; }
+
+ ///
+ /// Applications that the user got access to.
+ ///
+ public int[] ApplicationIds { get; set; }
+
+ ///
+ /// User that created the invite.
+ ///
+ public string InvitedByUserName { get; set; }
+
+ ///
+ /// Email address that the invitation was sent to.
+ ///
+ public string InvitedEmailAddress { get; set; }
+
+ ///
+ /// The user that accepted the invitation
+ ///
+ public string UserName { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Accounts/Events/LoginFailed.cs b/src/Server/Coderr.Server.Api/Core/Accounts/Events/LoginFailed.cs
similarity index 86%
rename from src/Server/OneTrueError.Api/Core/Accounts/Events/LoginFailed.cs
rename to src/Server/Coderr.Server.Api/Core/Accounts/Events/LoginFailed.cs
index 2deb179b..141ef93e 100644
--- a/src/Server/OneTrueError.Api/Core/Accounts/Events/LoginFailed.cs
+++ b/src/Server/Coderr.Server.Api/Core/Accounts/Events/LoginFailed.cs
@@ -1,43 +1,43 @@
-using System;
-using DotNetCqs;
-
-namespace OneTrueError.Api.Core.Accounts.Events
-{
- ///
- /// A login attepmt failed
- ///
- public class LoginFailed : ApplicationEvent
- {
- ///
- /// Creates a new instance of .
- ///
- /// user that attempted to login (userName was entered by the user, it might not exist)
- /// userName
- public LoginFailed(string userName)
- {
- if (userName == null) throw new ArgumentNullException("userName");
- UserName = userName;
- }
-
-
- ///
- /// If failed login was the reason (can't be set at the same time as )
- ///
- public bool InvalidLogin { get; set; }
-
- ///
- /// If account have been activated after registration.
- ///
- public bool IsActivated { get; set; }
-
- ///
- /// If account was or became locked.
- ///
- public bool IsLocked { get; set; }
-
- ///
- /// user that attempted to login (userName was entered by the user, it might not exist)
- ///
- public string UserName { get; private set; }
- }
+using System;
+
+namespace Coderr.Server.Api.Core.Accounts.Events
+{
+ ///
+ /// A login attempt failed
+ ///
+ [Message]
+ public class LoginFailed
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// user that attempted to login (userName was entered by the user, it might not exist)
+ /// userName
+ public LoginFailed(string userName)
+ {
+ if (userName == null) throw new ArgumentNullException("userName");
+ UserName = userName;
+ }
+
+
+ ///
+ /// If failed login was the reason (can't be set at the same time as )
+ ///
+ public bool InvalidLogin { get; set; }
+
+ ///
+ /// If account have been activated after registration.
+ ///
+ public bool IsActivated { get; set; }
+
+ ///
+ /// If account was or became locked.
+ ///
+ public bool IsLocked { get; set; }
+
+ ///
+ /// user that attempted to login (userName was entered by the user, it might not exist)
+ ///
+ public string UserName { get; private set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Accounts/NamespaceDoc.cs b/src/Server/Coderr.Server.Api/Core/Accounts/NamespaceDoc.cs
new file mode 100644
index 00000000..c12f8dd4
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Accounts/NamespaceDoc.cs
@@ -0,0 +1,16 @@
+using System.Runtime.CompilerServices;
+
+namespace Coderr.Server.Api.Core.Accounts
+{
+ // This file is Generated by the tool MarkdownToNamespaceDoc. ReadMe.md is the master.
+
+ ///
+ /// Account information (i.e. authentication and authorization)
+ ///
+ ///
+ ///
+ [CompilerGenerated]
+ internal class NamespaceDoc
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Accounts/Queries/AccountDTO.cs b/src/Server/Coderr.Server.Api/Core/Accounts/Queries/AccountDTO.cs
similarity index 92%
rename from src/Server/OneTrueError.Api/Core/Accounts/Queries/AccountDTO.cs
rename to src/Server/Coderr.Server.Api/Core/Accounts/Queries/AccountDTO.cs
index 060db483..f285968d 100644
--- a/src/Server/OneTrueError.Api/Core/Accounts/Queries/AccountDTO.cs
+++ b/src/Server/Coderr.Server.Api/Core/Accounts/Queries/AccountDTO.cs
@@ -1,46 +1,46 @@
-using System;
-
-namespace OneTrueError.Api.Core.Accounts.Queries
-{
- ///
- /// Account entity subset.
- ///
- public class AccountDTO
- {
- ///
- /// When the account was created
- ///
- public DateTime CreatedAtUtc { get; set; }
-
- ///
- /// Associated email address.
- ///
- //TODO: add to mapping
- public string Email { get; set; }
-
- ///
- /// Primary key
- ///
- public int Id { get; set; }
-
- ///
- /// Last time user logged in.
- ///
- public DateTime LastLoginAtUtc { get; set; }
-
- ///
- /// Current account state
- ///
- public AccountState State { get; set; }
-
- ///
- /// When the account was updated (changed first name etc)
- ///
- public DateTime UpdatedAtUtc { get; set; }
-
- ///
- /// Username
- ///
- public string UserName { get; set; }
- }
+using System;
+
+namespace Coderr.Server.Api.Core.Accounts.Queries
+{
+ ///
+ /// Account entity subset.
+ ///
+ public class AccountDTO
+ {
+ ///
+ /// When the account was created
+ ///
+ public DateTime CreatedAtUtc { get; set; }
+
+ ///
+ /// Associated email address.
+ ///
+ //TODO: add to mapping
+ public string Email { get; set; }
+
+ ///
+ /// Primary key
+ ///
+ public int Id { get; set; }
+
+ ///
+ /// Last time user logged in.
+ ///
+ public DateTime LastLoginAtUtc { get; set; }
+
+ ///
+ /// Current account state
+ ///
+ public AccountState State { get; set; }
+
+ ///
+ /// When the account was updated (changed first name etc)
+ ///
+ public DateTime UpdatedAtUtc { get; set; }
+
+ ///
+ /// Username
+ ///
+ public string UserName { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Accounts/Queries/AccountStateDTO.cs b/src/Server/Coderr.Server.Api/Core/Accounts/Queries/AccountStateDTO.cs
similarity index 89%
rename from src/Server/OneTrueError.Api/Core/Accounts/Queries/AccountStateDTO.cs
rename to src/Server/Coderr.Server.Api/Core/Accounts/Queries/AccountStateDTO.cs
index 4381ac4a..b1912301 100644
--- a/src/Server/OneTrueError.Api/Core/Accounts/Queries/AccountStateDTO.cs
+++ b/src/Server/Coderr.Server.Api/Core/Accounts/Queries/AccountStateDTO.cs
@@ -1,28 +1,28 @@
-namespace OneTrueError.Api.Core.Accounts.Queries
-{
- ///
- /// Account state
- ///
- public enum AccountState
- {
- ///
- /// Account have been created but not yet verified.
- ///
- VerificationRequired,
-
- ///
- /// Account is active
- ///
- Active,
-
- ///
- /// Account have been locked, typically by too many login attempts.
- ///
- Locked,
-
- ///
- /// Password reset have been requested (an password reset link have been sent).
- ///
- ResetPassword
- }
+namespace Coderr.Server.Api.Core.Accounts.Queries
+{
+ ///
+ /// Account state
+ ///
+ public enum AccountState
+ {
+ ///
+ /// Account have been created but not yet verified.
+ ///
+ VerificationRequired,
+
+ ///
+ /// Account is active
+ ///
+ Active,
+
+ ///
+ /// Account have been locked, typically by too many login attempts.
+ ///
+ Locked,
+
+ ///
+ /// Password reset have been requested (an password reset link have been sent).
+ ///
+ ResetPassword
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Accounts/Queries/FindAccountByUserName.cs b/src/Server/Coderr.Server.Api/Core/Accounts/Queries/FindAccountByUserName.cs
similarity index 85%
rename from src/Server/OneTrueError.Api/Core/Accounts/Queries/FindAccountByUserName.cs
rename to src/Server/Coderr.Server.Api/Core/Accounts/Queries/FindAccountByUserName.cs
index 4933d120..138de474 100644
--- a/src/Server/OneTrueError.Api/Core/Accounts/Queries/FindAccountByUserName.cs
+++ b/src/Server/Coderr.Server.Api/Core/Accounts/Queries/FindAccountByUserName.cs
@@ -1,33 +1,34 @@
-using System;
-using DotNetCqs;
-
-namespace OneTrueError.Api.Core.Accounts.Queries
-{
- ///
- /// Find an account by the given user name
- ///
- public class FindAccountByUserName : Query
- {
- ///
- /// Creates a new instance of .
- ///
- /// username
- public FindAccountByUserName(string userName)
- {
- if (userName == null) throw new ArgumentNullException("userName");
- UserName = userName;
- }
-
- ///
- /// Serialization constructor.
- ///
- protected FindAccountByUserName()
- {
- }
-
- ///
- /// Username
- ///
- public string UserName { get; private set; }
- }
+using System;
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Core.Accounts.Queries
+{
+ ///
+ /// Find an account by the given user name
+ ///
+ [Message]
+ public class FindAccountByUserName : Query
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// user name
+ public FindAccountByUserName(string userName)
+ {
+ if (userName == null) throw new ArgumentNullException("userName");
+ UserName = userName;
+ }
+
+ ///
+ /// Serialization constructor.
+ ///
+ protected FindAccountByUserName()
+ {
+ }
+
+ ///
+ /// Username
+ ///
+ public string UserName { get; private set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Accounts/Queries/FindAccountByUserNameResult.cs b/src/Server/Coderr.Server.Api/Core/Accounts/Queries/FindAccountByUserNameResult.cs
similarity index 93%
rename from src/Server/OneTrueError.Api/Core/Accounts/Queries/FindAccountByUserNameResult.cs
rename to src/Server/Coderr.Server.Api/Core/Accounts/Queries/FindAccountByUserNameResult.cs
index 5fd62711..b5c8c94a 100644
--- a/src/Server/OneTrueError.Api/Core/Accounts/Queries/FindAccountByUserNameResult.cs
+++ b/src/Server/Coderr.Server.Api/Core/Accounts/Queries/FindAccountByUserNameResult.cs
@@ -1,35 +1,35 @@
-using System;
-
-namespace OneTrueError.Api.Core.Accounts.Queries
-{
- ///
- /// Result for .
- ///
- public class FindAccountByUserNameResult
- {
- ///
- /// Creates a new instance of .
- ///
- /// account id
- /// Either username or FirstName LastName depending on what's available.
- /// displayName
- /// accountId
- public FindAccountByUserNameResult(int accountId, string displayName)
- {
- if (displayName == null) throw new ArgumentNullException("displayName");
- if (accountId <= 0) throw new ArgumentOutOfRangeException("accountId");
- AccountId = accountId;
- DisplayName = displayName;
- }
-
- ///
- /// Account id
- ///
- public int AccountId { get; private set; }
-
- ///
- /// Either username or FirstName LastName depending on what's available.
- ///
- public string DisplayName { get; private set; }
- }
+using System;
+
+namespace Coderr.Server.Api.Core.Accounts.Queries
+{
+ ///
+ /// Result for .
+ ///
+ public class FindAccountByUserNameResult
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// account id
+ /// Either username or FirstName LastName depending on what's available.
+ /// displayName
+ /// accountId
+ public FindAccountByUserNameResult(int accountId, string displayName)
+ {
+ if (displayName == null) throw new ArgumentNullException("displayName");
+ if (accountId <= 0) throw new ArgumentOutOfRangeException("accountId");
+ AccountId = accountId;
+ DisplayName = displayName;
+ }
+
+ ///
+ /// Account id
+ ///
+ public int AccountId { get; private set; }
+
+ ///
+ /// Either username or FirstName LastName depending on what's available.
+ ///
+ public string DisplayName { get; private set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Accounts/Queries/GetAccountById.cs b/src/Server/Coderr.Server.Api/Core/Accounts/Queries/GetAccountById.cs
similarity index 90%
rename from src/Server/OneTrueError.Api/Core/Accounts/Queries/GetAccountById.cs
rename to src/Server/Coderr.Server.Api/Core/Accounts/Queries/GetAccountById.cs
index ae660ee1..408def10 100644
--- a/src/Server/OneTrueError.Api/Core/Accounts/Queries/GetAccountById.cs
+++ b/src/Server/Coderr.Server.Api/Core/Accounts/Queries/GetAccountById.cs
@@ -1,35 +1,36 @@
-using System;
-using DotNetCqs;
-
-namespace OneTrueError.Api.Core.Accounts.Queries
-{
- ///
- /// Get account information.
- ///
- public class GetAccountById : Query
- {
- ///
- /// Creates a new instance of .
- ///
- /// Account id.
- public GetAccountById(int accountId)
- {
- if (accountId < 1)
- throw new ArgumentNullException("accountId");
-
- AccountId = accountId;
- }
-
- ///
- /// Serialization constructor
- ///
- protected GetAccountById()
- {
- }
-
- ///
- /// Account id.
- ///
- public int AccountId { get; private set; }
- }
+using System;
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Core.Accounts.Queries
+{
+ ///
+ /// Get account information.
+ ///
+ [Message]
+ public class GetAccountById : Query
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// Account id.
+ public GetAccountById(int accountId)
+ {
+ if (accountId < 1)
+ throw new ArgumentNullException("accountId");
+
+ AccountId = accountId;
+ }
+
+ ///
+ /// Serialization constructor
+ ///
+ protected GetAccountById()
+ {
+ }
+
+ ///
+ /// Account id.
+ ///
+ public int AccountId { get; private set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Accounts/Queries/GetAccountEmailById.cs b/src/Server/Coderr.Server.Api/Core/Accounts/Queries/GetAccountEmailById.cs
similarity index 90%
rename from src/Server/OneTrueError.Api/Core/Accounts/Queries/GetAccountEmailById.cs
rename to src/Server/Coderr.Server.Api/Core/Accounts/Queries/GetAccountEmailById.cs
index dace759d..06efd642 100644
--- a/src/Server/OneTrueError.Api/Core/Accounts/Queries/GetAccountEmailById.cs
+++ b/src/Server/Coderr.Server.Api/Core/Accounts/Queries/GetAccountEmailById.cs
@@ -1,33 +1,34 @@
-using System;
-using DotNetCqs;
-
-namespace OneTrueError.Api.Core.Accounts.Queries
-{
- ///
- /// Get email for a specific account
- ///
- public class GetAccountEmailById : Query
- {
- ///
- /// Creates a new instance of .
- ///
- /// account
- public GetAccountEmailById(int accountId)
- {
- if (accountId <= 0) throw new ArgumentOutOfRangeException("accountId");
- AccountId = accountId;
- }
-
- ///
- /// Serialization constructor.
- ///
- protected GetAccountEmailById()
- {
- }
-
- ///
- /// Account
- ///
- public int AccountId { get; private set; }
- }
+using System;
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Core.Accounts.Queries
+{
+ ///
+ /// Get email for a specific account
+ ///
+ [Message]
+ public class GetAccountEmailById : Query
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// account
+ public GetAccountEmailById(int accountId)
+ {
+ if (accountId <= 0) throw new ArgumentOutOfRangeException("accountId");
+ AccountId = accountId;
+ }
+
+ ///
+ /// Serialization constructor.
+ ///
+ protected GetAccountEmailById()
+ {
+ }
+
+ ///
+ /// Account
+ ///
+ public int AccountId { get; private set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Accounts/Queries/ListAccounts.cs b/src/Server/Coderr.Server.Api/Core/Accounts/Queries/ListAccounts.cs
new file mode 100644
index 00000000..540aa4f0
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Accounts/Queries/ListAccounts.cs
@@ -0,0 +1,11 @@
+using System.Collections.Generic;
+using System.Text;
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Core.Accounts.Queries
+{
+ [Message]
+ public class ListAccounts : Query
+ {
+ }
+}
diff --git a/src/Server/Coderr.Server.Api/Core/Accounts/Queries/ListAccountsResult.cs b/src/Server/Coderr.Server.Api/Core/Accounts/Queries/ListAccountsResult.cs
new file mode 100644
index 00000000..8c347a9b
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Accounts/Queries/ListAccountsResult.cs
@@ -0,0 +1,7 @@
+namespace Coderr.Server.Api.Core.Accounts.Queries
+{
+ public class ListAccountsResult
+ {
+ public ListAccountsResultItem[] Accounts { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Accounts/Queries/ListAccountsResultItem.cs b/src/Server/Coderr.Server.Api/Core/Accounts/Queries/ListAccountsResultItem.cs
new file mode 100644
index 00000000..b87b8510
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Accounts/Queries/ListAccountsResultItem.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Coderr.Server.Api.Core.Accounts.Queries
+{
+ public class ListAccountsResultItem
+ {
+ public int AccountId { get; set; }
+ public string UserName { get; set; }
+ public string Email { get; set; }
+ public DateTime CreatedAtUtc { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Accounts/ReadMe.md b/src/Server/Coderr.Server.Api/Core/Accounts/ReadMe.md
similarity index 100%
rename from src/Server/OneTrueError.Api/Core/Accounts/ReadMe.md
rename to src/Server/Coderr.Server.Api/Core/Accounts/ReadMe.md
diff --git a/src/Server/OneTrueError.Api/Core/Accounts/RegisterSimple.cs b/src/Server/Coderr.Server.Api/Core/Accounts/RegisterSimple.cs
similarity index 88%
rename from src/Server/OneTrueError.Api/Core/Accounts/RegisterSimple.cs
rename to src/Server/Coderr.Server.Api/Core/Accounts/RegisterSimple.cs
index 222d5d36..fa49f513 100644
--- a/src/Server/OneTrueError.Api/Core/Accounts/RegisterSimple.cs
+++ b/src/Server/Coderr.Server.Api/Core/Accounts/RegisterSimple.cs
@@ -1,40 +1,39 @@
-using System;
-using DotNetCqs;
-
-namespace OneTrueError.Api.Core.Accounts
-{
- ///
- /// Register using email address only.
- ///
- ///
- ///
- /// A temporary password is generated and included in the eamil. The user name is generated from
- /// the name part of the email address.
- ///
- ///
- public class RegisterSimple : Command
- {
- ///
- /// Create a new instance of .
- ///
- /// Email address
- /// emailAddress
- public RegisterSimple(string emailAddress)
- {
- if (emailAddress == null) throw new ArgumentNullException("emailAddress");
- EmailAddress = emailAddress;
- }
-
- ///
- /// Serialization constructor.
- ///
- protected RegisterSimple()
- {
- }
-
- ///
- /// Email address
- ///
- public string EmailAddress { get; private set; }
- }
+using System;
+
+namespace Coderr.Server.Api.Core.Accounts
+{
+ ///
+ /// Register using email address only.
+ ///
+ ///
+ ///
+ /// A temporary password is generated and included in the eamil. The user name is generated from
+ /// the name part of the email address.
+ ///
+ ///
+ public class RegisterSimple
+ {
+ ///
+ /// Create a new instance of .
+ ///
+ /// Email address
+ /// emailAddress
+ public RegisterSimple(string emailAddress)
+ {
+ if (emailAddress == null) throw new ArgumentNullException("emailAddress");
+ EmailAddress = emailAddress;
+ }
+
+ ///
+ /// Serialization constructor.
+ ///
+ protected RegisterSimple()
+ {
+ }
+
+ ///
+ /// Email address
+ ///
+ public string EmailAddress { get; private set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Accounts/Requests/AcceptInvitation.cs b/src/Server/Coderr.Server.Api/Core/Accounts/Requests/AcceptInvitation.cs
similarity index 93%
rename from src/Server/OneTrueError.Api/Core/Accounts/Requests/AcceptInvitation.cs
rename to src/Server/Coderr.Server.Api/Core/Accounts/Requests/AcceptInvitation.cs
index e05bb965..a5703232 100644
--- a/src/Server/OneTrueError.Api/Core/Accounts/Requests/AcceptInvitation.cs
+++ b/src/Server/Coderr.Server.Api/Core/Accounts/Requests/AcceptInvitation.cs
@@ -1,115 +1,115 @@
-using System;
-using System.ComponentModel.DataAnnotations;
-using DotNetCqs;
-
-namespace OneTrueError.Api.Core.Accounts.Requests
-{
- ///
- /// You must create an account before accepting the invitation
- ///
- public class AcceptInvitation : Request
- {
- ///
- /// Creates a new instance of .
- ///
- /// username
- /// clear text password
- /// Key from the generated email.
- public AcceptInvitation(string userName, string password, string invitationKey)
- {
- if (userName == null) throw new ArgumentNullException("userName");
- if (password == null) throw new ArgumentNullException("password");
- if (invitationKey == null) throw new ArgumentNullException("invitationKey");
-
- UserName = userName;
- Password = password;
- InvitationKey = invitationKey;
- }
-
- ///
- /// Creates a new instance of .
- ///
- /// Existing account
- /// Key from the generated email.
- ///
- ///
- /// Invite to an existing account.
- ///
- ///
- public AcceptInvitation(int accountId, string invitationKey)
- {
- if (string.IsNullOrEmpty(invitationKey)) throw new ArgumentNullException("invitationKey");
- if (accountId <= 0) throw new ArgumentOutOfRangeException("accountId");
-
- AccountId = accountId;
- InvitationKey = invitationKey;
- }
-
-
- ///
- /// Serialization constructor
- ///
- protected AcceptInvitation()
- {
- }
-
-
- ///
- /// The email that was used when creating an account.
- ///
- ///
- ///
- /// Do note that this email can be different compared to the one that was used when sending the invitation. Make
- /// sure that this one is assigned to the created account.
- ///
- ///
- [Required]
- public string AcceptedEmail { get; set; }
-
- ///
- /// Invite to an existing account
- ///
- ///
- ///
- /// Alternative to the / combination
- ///
- ///
- public int AccountId { get; set; }
-
- ///
- /// Email that the inviation was sent to
- ///
- public string EmailUsedForTheInvitation { get; set; }
-
-
- ///
- /// First name
- ///
- public string FirstName { get; set; }
-
- ///
- /// Invitation key from the invitation email.
- ///
- public string InvitationKey { get; private set; }
-
- ///
- /// Last name
- ///
- public string LastName { get; set; }
-
- ///
- /// Clear text password
- ///
- ///
- public string Password { get; private set; }
-
- ///
- /// Username as entered by the user
- ///
- ///
- /// Used together with
- /// Alternative to
- ///
- public string UserName { get; private set; }
- }
+using System;
+using System.ComponentModel.DataAnnotations;
+
+namespace Coderr.Server.Api.Core.Accounts.Requests
+{
+ ///
+ /// You must create an account before accepting the invitation
+ ///
+ [Command]
+ public class AcceptInvitation
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// username
+ /// clear text password
+ /// Key from the generated email.
+ public AcceptInvitation(string userName, string password, string invitationKey)
+ {
+ if (userName == null) throw new ArgumentNullException("userName");
+ if (password == null) throw new ArgumentNullException("password");
+ if (invitationKey == null) throw new ArgumentNullException("invitationKey");
+
+ UserName = userName;
+ Password = password;
+ InvitationKey = invitationKey;
+ }
+
+ ///
+ /// Creates a new instance of .
+ ///
+ /// Existing account
+ /// Key from the generated email.
+ ///
+ ///
+ /// Invite to an existing account.
+ ///
+ ///
+ public AcceptInvitation(int accountId, string invitationKey)
+ {
+ if (string.IsNullOrEmpty(invitationKey)) throw new ArgumentNullException("invitationKey");
+ if (accountId <= 0) throw new ArgumentOutOfRangeException("accountId");
+
+ AccountId = accountId;
+ InvitationKey = invitationKey;
+ }
+
+
+ ///
+ /// Serialization constructor
+ ///
+ protected AcceptInvitation()
+ {
+ }
+
+
+ ///
+ /// The email that was used when creating an account.
+ ///
+ ///
+ ///
+ /// Do note that this email can be different compared to the one that was used when sending the invitation. Make
+ /// sure that this one is assigned to the created account.
+ ///
+ ///
+ [Required]
+ public string AcceptedEmail { get; set; }
+
+ ///
+ /// Invite to an existing account
+ ///
+ ///
+ ///
+ /// Alternative to the / combination
+ ///
+ ///
+ public int AccountId { get; set; }
+
+ ///
+ /// Email that the inviation was sent to
+ ///
+ public string EmailUsedForTheInvitation { get; set; }
+
+
+ ///
+ /// First name
+ ///
+ public string FirstName { get; set; }
+
+ ///
+ /// Invitation key from the invitation email.
+ ///
+ public string InvitationKey { get; private set; }
+
+ ///
+ /// Last name
+ ///
+ public string LastName { get; set; }
+
+ ///
+ /// Clear text password
+ ///
+ ///
+ public string Password { get; private set; }
+
+ ///
+ /// Username as entered by the user
+ ///
+ ///
+ /// Used together with
+ /// Alternative to
+ ///
+ public string UserName { get; private set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Accounts/Requests/ChangePassword.cs b/src/Server/Coderr.Server.Api/Core/Accounts/Requests/ChangePassword.cs
similarity index 86%
rename from src/Server/OneTrueError.Api/Core/Accounts/Requests/ChangePassword.cs
rename to src/Server/Coderr.Server.Api/Core/Accounts/Requests/ChangePassword.cs
index 630b9038..44136fe6 100644
--- a/src/Server/OneTrueError.Api/Core/Accounts/Requests/ChangePassword.cs
+++ b/src/Server/Coderr.Server.Api/Core/Accounts/Requests/ChangePassword.cs
@@ -1,53 +1,53 @@
-using System;
-using DotNetCqs;
-using OneTrueError.Api.Core.Accounts.Commands;
-
-namespace OneTrueError.Api.Core.Accounts.Requests
-{
- ///
- /// Change password.
- ///
- ///
- ///
- /// Done when the user knows the current one but want to switch. Otherwise use .
- ///
- ///
- public class ChangePassword : Request
- {
- ///
- /// Create a new instance of .
- ///
- /// Current password
- /// Password to change to.
- public ChangePassword(string currentPassword, string newPassword)
- {
- if (currentPassword == null) throw new ArgumentNullException(nameof(currentPassword));
- if (newPassword == null) throw new ArgumentNullException(nameof(newPassword));
- CurrentPassword = currentPassword;
- NewPassword = newPassword;
- }
-
- ///
- /// Serialization constructor.
- ///
- protected ChangePassword()
- {
- }
-
- ///
- /// Current password
- ///
- public string CurrentPassword { get; private set; }
-
- ///
- /// Password to change to.
- ///
- public string NewPassword { get; private set; }
-
- ///
- /// Assigned by the CQS library
- ///
- [IgnoreField]
- public int UserId { get; set; }
- }
+using System;
+using Coderr.Server.Api.Core.Accounts.Commands;
+
+namespace Coderr.Server.Api.Core.Accounts.Requests
+{
+ ///
+ /// Change password.
+ ///
+ ///
+ ///
+ /// Done when the user knows the current one but want to switch. Otherwise use .
+ ///
+ ///
+ [Command]
+ public class ChangePassword
+ {
+ ///
+ /// Create a new instance of .
+ ///
+ /// Current password
+ /// Password to change to.
+ public ChangePassword(string currentPassword, string newPassword)
+ {
+ if (currentPassword == null) throw new ArgumentNullException(nameof(currentPassword));
+ if (newPassword == null) throw new ArgumentNullException(nameof(newPassword));
+ CurrentPassword = currentPassword;
+ NewPassword = newPassword;
+ }
+
+ ///
+ /// Serialization constructor.
+ ///
+ protected ChangePassword()
+ {
+ }
+
+ ///
+ /// Current password
+ ///
+ public string CurrentPassword { get; private set; }
+
+ ///
+ /// Password to change to.
+ ///
+ public string NewPassword { get; private set; }
+
+ ///
+ /// Assigned by the CQS library
+ ///
+ [IgnoreField]
+ public int UserId { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Accounts/Requests/ReadMe.md b/src/Server/Coderr.Server.Api/Core/Accounts/Requests/ReadMe.md
new file mode 100644
index 00000000..fcddd636
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Accounts/Requests/ReadMe.md
@@ -0,0 +1,3 @@
+These are now part of the AccountService and will be moved there.
+
+The API will rather be HTTP services in the future, where these messages are DTOs
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Accounts/Requests/ValidateNewLoginReply.cs b/src/Server/Coderr.Server.Api/Core/Accounts/Requests/ValidateNewLoginReply.cs
new file mode 100644
index 00000000..432037c7
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Accounts/Requests/ValidateNewLoginReply.cs
@@ -0,0 +1,18 @@
+namespace Coderr.Server.Api.Core.Accounts.Requests
+{
+ ///
+ /// DTO
+ ///
+ public class ValidateNewLoginReply
+ {
+ ///
+ /// The given email address is already associated with an account.
+ ///
+ public bool EmailIsTaken { get; set; }
+
+ ///
+ /// The given user name is already associated with an account.
+ ///
+ public bool UserNameIsTaken { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/ApiKeys/Commands/CreateApiKey.cs b/src/Server/Coderr.Server.Api/Core/ApiKeys/Commands/CreateApiKey.cs
new file mode 100644
index 00000000..9af258d6
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/ApiKeys/Commands/CreateApiKey.cs
@@ -0,0 +1,92 @@
+using System;
+
+namespace Coderr.Server.Api.Core.ApiKeys.Commands
+{
+ ///
+ /// Create a new API key
+ ///
+ ///
+ /// API keys are used to be able to communicate with the Coderr server through the HTTP API.
+ ///
+ [AuthorizeRoles("SysAdmin")]
+ [Message]
+ public class CreateApiKey
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// applicationName;apiKey;sharedSecret;applicationIds
+ public CreateApiKey(string applicationName, string apiKey, string sharedSecret, int[] applicationIds)
+ {
+ ApplicationName = applicationName ?? throw new ArgumentNullException("applicationName");
+ ApiKey = apiKey ?? throw new ArgumentNullException("apiKey");
+ SharedSecret = sharedSecret ?? throw new ArgumentNullException("sharedSecret");
+ ApplicationIds = applicationIds ?? throw new ArgumentNullException("applicationIds");
+ }
+
+ ///
+ /// Creates a new instance of .
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public CreateApiKey(string applicationName, string apiKey, string sharedSecret)
+ {
+ ApplicationName = applicationName ?? throw new ArgumentNullException("applicationName");
+ ApiKey = apiKey ?? throw new ArgumentNullException("apiKey");
+ SharedSecret = sharedSecret ?? throw new ArgumentNullException("sharedSecret");
+ ApplicationIds = new int[0];
+ }
+
+ ///
+ /// Serialization constructor
+ ///
+ protected CreateApiKey()
+ {
+ }
+
+
+ ///
+ /// Must always be the one that creates the key (will be assigned by the CommandBus per convention)
+ ///
+ public int AccountId { get; set; }
+
+ ///
+ /// Generated API key
+ ///
+ public string ApiKey { get; set; }
+
+ ///
+ /// applications that this key may modify. Empty = allow for all applications.
+ ///
+ public int[] ApplicationIds { get; set; }
+
+ ///
+ /// Application that uses this API key
+ ///
+ public string ApplicationName { get; set; }
+
+ ///
+ /// Used to sign all requests.
+ ///
+ public string SharedSecret { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/ApiKeys/Commands/DeleteApiKey.cs b/src/Server/Coderr.Server.Api/Core/ApiKeys/Commands/DeleteApiKey.cs
similarity index 88%
rename from src/Server/OneTrueError.Api/Core/ApiKeys/Commands/DeleteApiKey.cs
rename to src/Server/Coderr.Server.Api/Core/ApiKeys/Commands/DeleteApiKey.cs
index 63225e94..f6f7ff19 100644
--- a/src/Server/OneTrueError.Api/Core/ApiKeys/Commands/DeleteApiKey.cs
+++ b/src/Server/Coderr.Server.Api/Core/ApiKeys/Commands/DeleteApiKey.cs
@@ -1,51 +1,52 @@
-using System;
-using DotNetCqs;
-
-namespace OneTrueError.Api.Core.ApiKeys.Commands
-{
- ///
- /// Delete an API key.
- ///
- public class DeleteApiKey : Command
- {
- ///
- /// Serialization constructor
- ///
- protected DeleteApiKey()
- {
- }
-
- ///
- /// Creates a new instance of .
- ///
- /// PK
- public DeleteApiKey(int id)
- {
- Id = id;
- }
-
- ///
- /// Creates a new instance of .
- ///
- /// The generated ApiKey
- public DeleteApiKey(string apiKey)
- {
- if (apiKey == null) throw new ArgumentNullException("apiKey");
- Guid guid;
- if (!Guid.TryParse(apiKey, out guid))
- throw new ArgumentException("Not a valid api key: " + apiKey, "apiKey");
-
- ApiKey = apiKey;
- }
-
- ///
- /// generated api key (if specified)
- ///
- public string ApiKey { get; private set; }
-
- ///
- /// PK (if specified)
- ///
- public int Id { get; private set; }
- }
+using System;
+
+namespace Coderr.Server.Api.Core.ApiKeys.Commands
+{
+ ///
+ /// Delete an API key.
+ ///
+ [AuthorizeRoles("SysAdmin")]
+ [Message]
+ public class DeleteApiKey
+ {
+ ///
+ /// Serialization constructor
+ ///
+ protected DeleteApiKey()
+ {
+ }
+
+ ///
+ /// Creates a new instance of .
+ ///
+ /// PK
+ public DeleteApiKey(int id)
+ {
+ Id = id;
+ }
+
+ ///
+ /// Creates a new instance of .
+ ///
+ /// The generated ApiKey
+ public DeleteApiKey(string apiKey)
+ {
+ if (apiKey == null) throw new ArgumentNullException("apiKey");
+ Guid guid;
+ if (!Guid.TryParse(apiKey, out guid))
+ throw new ArgumentException("Not a valid api key: " + apiKey, "apiKey");
+
+ ApiKey = apiKey;
+ }
+
+ ///
+ /// generated api key (if specified)
+ ///
+ public string ApiKey { get; private set; }
+
+ ///
+ /// PK (if specified)
+ ///
+ public int Id { get; private set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/ApiKeys/Commands/EditApiKey.cs b/src/Server/Coderr.Server.Api/Core/ApiKeys/Commands/EditApiKey.cs
new file mode 100644
index 00000000..71e71361
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/ApiKeys/Commands/EditApiKey.cs
@@ -0,0 +1,47 @@
+using System;
+
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Local
+
+namespace Coderr.Server.Api.Core.ApiKeys.Commands
+{
+ ///
+ /// Create a new api key
+ ///
+ [AuthorizeRoles("SysAdmin")]
+ [Message]
+ public class EditApiKey
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ public EditApiKey(int id)
+ {
+ if (id <= 0) throw new ArgumentOutOfRangeException(nameof(id));
+ Id = id;
+ }
+
+
+ ///
+ /// Serialization constructor
+ ///
+ protected EditApiKey()
+ {
+ }
+
+
+ ///
+ /// applications that this key may modify. Empty = allow for all applications.
+ ///
+ public int[] ApplicationIds { get; set; }
+
+ ///
+ /// Application that uses this api key
+ ///
+ public string ApplicationName { get; set; }
+
+ ///
+ /// Key id
+ ///
+ public int Id { get; private set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/ApiKeys/Events/ApiKeyCreated.cs b/src/Server/Coderr.Server.Api/Core/ApiKeys/Events/ApiKeyCreated.cs
similarity index 95%
rename from src/Server/OneTrueError.Api/Core/ApiKeys/Events/ApiKeyCreated.cs
rename to src/Server/Coderr.Server.Api/Core/ApiKeys/Events/ApiKeyCreated.cs
index 4ee5bf1f..e0801678 100644
--- a/src/Server/OneTrueError.Api/Core/ApiKeys/Events/ApiKeyCreated.cs
+++ b/src/Server/Coderr.Server.Api/Core/ApiKeys/Events/ApiKeyCreated.cs
@@ -1,12 +1,12 @@
using System;
-using DotNetCqs;
-namespace OneTrueError.Api.Core.ApiKeys.Events
+namespace Coderr.Server.Api.Core.ApiKeys.Events
{
- ///
- /// A new API key has been created.
+ ///
+ /// A new API key has been created.
///
- public class ApiKeyCreated : ApplicationEvent
+ [Message]
+ public class ApiKeyCreated
{
///
/// Creates a new instance of .
diff --git a/src/Server/Coderr.Server.Api/Core/ApiKeys/Events/ApiKeyRemoved.cs b/src/Server/Coderr.Server.Api/Core/ApiKeys/Events/ApiKeyRemoved.cs
new file mode 100644
index 00000000..644fa18e
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/ApiKeys/Events/ApiKeyRemoved.cs
@@ -0,0 +1,10 @@
+namespace Coderr.Server.Api.Core.ApiKeys.Events
+{
+ ///
+ /// A API key was removed from the system
+ ///
+ [Event]
+ public class ApiKeyRemoved
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/ApiKeys/Queries/GetApiKey.cs b/src/Server/Coderr.Server.Api/Core/ApiKeys/Queries/GetApiKey.cs
similarity index 93%
rename from src/Server/OneTrueError.Api/Core/ApiKeys/Queries/GetApiKey.cs
rename to src/Server/Coderr.Server.Api/Core/ApiKeys/Queries/GetApiKey.cs
index 5c8c0d8d..d4447ff3 100644
--- a/src/Server/OneTrueError.Api/Core/ApiKeys/Queries/GetApiKey.cs
+++ b/src/Server/Coderr.Server.Api/Core/ApiKeys/Queries/GetApiKey.cs
@@ -1,51 +1,52 @@
-using System;
-using DotNetCqs;
-
-namespace OneTrueError.Api.Core.ApiKeys.Queries
-{
- ///
- /// Get information about an API key
- ///
- public class GetApiKey : Query
- {
- ///
- /// Serialization constructor
- ///
- protected GetApiKey()
- {
- }
-
- ///
- /// Creates a new instance of .
- ///
- /// PK
- public GetApiKey(int id)
- {
- Id = id;
- }
-
- ///
- /// Creates a new instance of .
- ///
- /// The generated ApiKey
- public GetApiKey(string apiKey)
- {
- if (apiKey == null) throw new ArgumentNullException("apiKey");
- Guid guid;
- if (!Guid.TryParse(apiKey, out guid))
- throw new ArgumentException("Not a valid api key: " + apiKey, "apiKey");
-
- ApiKey = apiKey;
- }
-
- ///
- /// generated api key (if specified)
- ///
- public string ApiKey { get; private set; }
-
- ///
- /// PK (if specified)
- ///
- public int Id { get; private set; }
- }
+using System;
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Core.ApiKeys.Queries
+{
+ ///
+ /// Get information about an API key
+ ///
+ [Message]
+ public class GetApiKey : Query
+ {
+ ///
+ /// Serialization constructor
+ ///
+ protected GetApiKey()
+ {
+ }
+
+ ///
+ /// Creates a new instance of .
+ ///
+ /// PK
+ public GetApiKey(int id)
+ {
+ Id = id;
+ }
+
+ ///
+ /// Creates a new instance of .
+ ///
+ /// The generated ApiKey
+ public GetApiKey(string apiKey)
+ {
+ if (apiKey == null) throw new ArgumentNullException("apiKey");
+ Guid guid;
+ if (!Guid.TryParse(apiKey, out guid))
+ throw new ArgumentException("Not a valid api key: " + apiKey, "apiKey");
+
+ ApiKey = apiKey;
+ }
+
+ ///
+ /// generated api key (if specified)
+ ///
+ public string ApiKey { get; private set; }
+
+ ///
+ /// PK (if specified)
+ ///
+ public int Id { get; private set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/ApiKeys/Queries/GetApiKeyResult.cs b/src/Server/Coderr.Server.Api/Core/ApiKeys/Queries/GetApiKeyResult.cs
similarity index 92%
rename from src/Server/OneTrueError.Api/Core/ApiKeys/Queries/GetApiKeyResult.cs
rename to src/Server/Coderr.Server.Api/Core/ApiKeys/Queries/GetApiKeyResult.cs
index 9bbdd784..869f9a33 100644
--- a/src/Server/OneTrueError.Api/Core/ApiKeys/Queries/GetApiKeyResult.cs
+++ b/src/Server/Coderr.Server.Api/Core/ApiKeys/Queries/GetApiKeyResult.cs
@@ -1,48 +1,48 @@
-using System;
-
-namespace OneTrueError.Api.Core.ApiKeys.Queries
-{
- ///
- /// Result for .
- ///
- public class GetApiKeyResult
- {
- ///
- /// Application ids that we've been granted to work with
- ///
- public GetApiKeyResultApplication[] AllowedApplications { get; set; }
-
- ///
- /// Application that will be using this key
- ///
- public string ApplicationName { get; set; }
-
-
- ///
- /// When this key was generated
- ///
- public DateTime CreatedAtUtc { get; set; }
-
- ///
- /// AccountId that generated this key
- ///
- public int CreatedById { get; set; }
-
- ///
- /// Api key
- ///
- public string GeneratedKey { get; set; }
-
-
- ///
- /// PK
- ///
- public int Id { get; set; }
-
-
- ///
- /// Used when generating signatures.
- ///
- public string SharedSecret { get; set; }
- }
+using System;
+
+namespace Coderr.Server.Api.Core.ApiKeys.Queries
+{
+ ///
+ /// Result for .
+ ///
+ public class GetApiKeyResult
+ {
+ ///
+ /// Application ids that we've been granted to work with
+ ///
+ public GetApiKeyResultApplication[] AllowedApplications { get; set; }
+
+ ///
+ /// Application that will be using this key
+ ///
+ public string ApplicationName { get; set; }
+
+
+ ///
+ /// When this key was generated
+ ///
+ public DateTime CreatedAtUtc { get; set; }
+
+ ///
+ /// AccountId that generated this key
+ ///
+ public int CreatedById { get; set; }
+
+ ///
+ /// Api key
+ ///
+ public string GeneratedKey { get; set; }
+
+
+ ///
+ /// PK
+ ///
+ public int Id { get; set; }
+
+
+ ///
+ /// Used when generating signatures.
+ ///
+ public string SharedSecret { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/ApiKeys/Queries/GetApiKeyResultApplication.cs b/src/Server/Coderr.Server.Api/Core/ApiKeys/Queries/GetApiKeyResultApplication.cs
similarity index 86%
rename from src/Server/OneTrueError.Api/Core/ApiKeys/Queries/GetApiKeyResultApplication.cs
rename to src/Server/Coderr.Server.Api/Core/ApiKeys/Queries/GetApiKeyResultApplication.cs
index 7528845b..fca1862f 100644
--- a/src/Server/OneTrueError.Api/Core/ApiKeys/Queries/GetApiKeyResultApplication.cs
+++ b/src/Server/Coderr.Server.Api/Core/ApiKeys/Queries/GetApiKeyResultApplication.cs
@@ -1,19 +1,19 @@
-namespace OneTrueError.Api.Core.ApiKeys.Queries
-{
- ///
- /// An allowed application for .
- ///
- public class GetApiKeyResultApplication
- {
- ///
- /// Application id (PK)
- ///
- public int ApplicationId { get; set; }
-
-
- ///
- /// Name of the application
- ///
- public string ApplicationName { get; set; }
- }
+namespace Coderr.Server.Api.Core.ApiKeys.Queries
+{
+ ///
+ /// An allowed application for .
+ ///
+ public class GetApiKeyResultApplication
+ {
+ ///
+ /// Application id (PK)
+ ///
+ public int ApplicationId { get; set; }
+
+
+ ///
+ /// Name of the application
+ ///
+ public string ApplicationName { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/ApiKeys/Queries/ListApiKeys.cs b/src/Server/Coderr.Server.Api/Core/ApiKeys/Queries/ListApiKeys.cs
new file mode 100644
index 00000000..bd217a17
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/ApiKeys/Queries/ListApiKeys.cs
@@ -0,0 +1,12 @@
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Core.ApiKeys.Queries
+{
+ ///
+ /// List all created keys
+ ///
+ [Message]
+ public class ListApiKeys : Query
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/ApiKeys/Queries/ListApiKeysResult.cs b/src/Server/Coderr.Server.Api/Core/ApiKeys/Queries/ListApiKeysResult.cs
similarity index 81%
rename from src/Server/OneTrueError.Api/Core/ApiKeys/Queries/ListApiKeysResult.cs
rename to src/Server/Coderr.Server.Api/Core/ApiKeys/Queries/ListApiKeysResult.cs
index b5896464..61bd3890 100644
--- a/src/Server/OneTrueError.Api/Core/ApiKeys/Queries/ListApiKeysResult.cs
+++ b/src/Server/Coderr.Server.Api/Core/ApiKeys/Queries/ListApiKeysResult.cs
@@ -1,13 +1,13 @@
-namespace OneTrueError.Api.Core.ApiKeys.Queries
-{
- ///
- /// Result for .
- ///
- public class ListApiKeysResult
- {
- ///
- /// All created keys
- ///
- public ListApiKeysResultItem[] Keys { get; set; }
- }
+namespace Coderr.Server.Api.Core.ApiKeys.Queries
+{
+ ///
+ /// Result for .
+ ///
+ public class ListApiKeysResult
+ {
+ ///
+ /// All created keys
+ ///
+ public ListApiKeysResultItem[] Keys { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/ApiKeys/Queries/ListApiKeysResultItem.cs b/src/Server/Coderr.Server.Api/Core/ApiKeys/Queries/ListApiKeysResultItem.cs
similarity index 88%
rename from src/Server/OneTrueError.Api/Core/ApiKeys/Queries/ListApiKeysResultItem.cs
rename to src/Server/Coderr.Server.Api/Core/ApiKeys/Queries/ListApiKeysResultItem.cs
index 018b9a0f..20bfc7bf 100644
--- a/src/Server/OneTrueError.Api/Core/ApiKeys/Queries/ListApiKeysResultItem.cs
+++ b/src/Server/Coderr.Server.Api/Core/ApiKeys/Queries/ListApiKeysResultItem.cs
@@ -1,23 +1,23 @@
-namespace OneTrueError.Api.Core.ApiKeys.Queries
-{
- ///
- /// Item for .
- ///
- public class ListApiKeysResultItem
- {
- ///
- /// Key to use
- ///
- public string ApiKey { get; set; }
-
- ///
- /// Application name, i.e. name of the application that uses this key.
- ///
- public string ApplicationName { get; set; }
-
- ///
- /// Identity
- ///
- public int Id { get; set; }
- }
+namespace Coderr.Server.Api.Core.ApiKeys.Queries
+{
+ ///
+ /// Item for .
+ ///
+ public class ListApiKeysResultItem
+ {
+ ///
+ /// Key to use
+ ///
+ public string ApiKey { get; set; }
+
+ ///
+ /// Application name, i.e. name of the application that uses this key.
+ ///
+ public string ApplicationName { get; set; }
+
+ ///
+ /// Identity
+ ///
+ public int Id { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/ApiKeys/ReadMe.md b/src/Server/Coderr.Server.Api/Core/ApiKeys/ReadMe.md
new file mode 100644
index 00000000..92f887cc
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/ApiKeys/ReadMe.md
@@ -0,0 +1,32 @@
+ApiKeys
+========
+
+Used to allow external applications to talk with codeRR.
+
+
+## Example usage
+
+The following example calls a local codeRR server to retreive applications.
+
+```csharp
+var client = new ServerApiClient();
+var uri = new Uri("http://yourServer/coderr/");
+client.Open(uri, "theApiKey", "sharedSecret");
+var apps = await client.QueryAsync(new GetApplicationList());
+```
+
+Result (serialized as JSON):
+
+```javascript
+[{
+ "Id" : 1,
+ "Name" : "PublicWeb"
+ }, {
+ "Id" : 9,
+ "Name" : "Time reporting system"
+ }, {
+ "Id" : 10,
+ "Name" : "Coffee monitor"
+ }
+]
+```
diff --git a/src/Server/Coderr.Server.Api/Core/Applications/ApplicationListItem.cs b/src/Server/Coderr.Server.Api/Core/Applications/ApplicationListItem.cs
new file mode 100644
index 00000000..e9d86f7a
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Applications/ApplicationListItem.cs
@@ -0,0 +1,64 @@
+using System;
+using Coderr.Server.Api.Core.Applications.Queries;
+
+namespace Coderr.Server.Api.Core.Applications
+{
+ ///
+ /// Result item for
+ ///
+ public class ApplicationListItem
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// application identity
+ /// name of the application
+ public ApplicationListItem(int id, string name)
+ {
+ if (id <= 0) throw new ArgumentOutOfRangeException("id");
+
+ Id = id;
+ Name = name ?? throw new ArgumentNullException("name");
+ }
+
+ ///
+ /// Serialization constructor
+ ///
+ protected ApplicationListItem()
+ {
+ }
+
+ ///
+ /// Group that this application belongs to.
+ ///
+ public int GroupId { get; set; }
+
+ ///
+ /// Name of the group
+ ///
+ public string GroupName { get; set; }
+
+ ///
+ /// Id of the application (primary key)
+ ///
+ public int Id { get; set; }
+
+ ///
+ /// User that requested this list is the admin of the specified application.
+ ///
+ public bool IsAdmin { get; set; }
+
+ ///
+ /// Application name as entered by the user.
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// Number of full time developers.
+ ///
+ ///
+ /// null = not specified
+ ///
+ public decimal? NumberOfDevelopers { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Applications/Commands/AddTeamMember.cs b/src/Server/Coderr.Server.Api/Core/Applications/Commands/AddTeamMember.cs
new file mode 100644
index 00000000..5294c573
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Applications/Commands/AddTeamMember.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Coderr.Server.Api.Core.Applications.Commands
+{
+ [Command]
+ public class AddTeamMember
+ {
+ public int UserToAdd { get; set; }
+ public int ApplicationId { get; set; }
+
+ public string[] Roles { get; set; }
+ }
+}
diff --git a/src/Server/Coderr.Server.Api/Core/Applications/Commands/CreateApplication.cs b/src/Server/Coderr.Server.Api/Core/Applications/Commands/CreateApplication.cs
new file mode 100644
index 00000000..87f7d151
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Applications/Commands/CreateApplication.cs
@@ -0,0 +1,69 @@
+using System;
+
+namespace Coderr.Server.Api.Core.Applications.Commands
+{
+ ///
+ /// Create a new application.
+ ///
+ [Message]
+ public class CreateApplication
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// Name of the application (as entered by the user)
+ /// Application type
+ public CreateApplication(string name, TypeOfApplication typeOfApplication)
+ {
+ if (name == null) throw new ArgumentNullException("name");
+ if (!Enum.IsDefined(typeof(TypeOfApplication), typeOfApplication))
+
+ throw new ArgumentOutOfRangeException("typeOfApplication");
+ Name = name;
+ TypeOfApplication = typeOfApplication;
+ }
+
+ ///
+ /// Generated application key
+ ///
+ public string ApplicationKey { get; set; }
+
+ ///
+ /// User specified name
+ ///
+ public string Name { get; set; }
+
+
+ ///
+ /// Application type
+ ///
+ public TypeOfApplication TypeOfApplication { get; set; }
+
+
+ ///
+ /// Account id for the user that sent the command
+ ///
+ [IgnoreField]
+ public int UserId { get; set; }
+
+ ///
+ /// Estimated number of errors
+ ///
+ public int? NumberOfErrors { get; set; }
+
+ ///
+ /// Number of developers that work full time with this application.
+ ///
+ public decimal? NumberOfDevelopers { get; set; }
+
+ ///
+ /// Number of days to keep new incidents.
+ ///
+ public int? RetentionDays { get; set; }
+
+ ///
+ /// Application group that this application should be part of.
+ ///
+ public int? GroupId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Applications/Commands/CreateApplicationGroup.cs b/src/Server/Coderr.Server.Api/Core/Applications/Commands/CreateApplicationGroup.cs
new file mode 100644
index 00000000..c3375a84
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Applications/Commands/CreateApplicationGroup.cs
@@ -0,0 +1,37 @@
+using System;
+
+namespace Coderr.Server.Api.Core.Applications.Commands
+{
+ ///
+ /// Create an application group.
+ ///
+ ///
+ ///
+ /// Groups are used to group similar applications together.
+ ///
+ ///
+ [Command]
+ public class CreateApplicationGroup
+ {
+ ///
+ /// Creates a new instance of the class.
+ ///
+ /// Name of the new group (human friendly name)
+ public CreateApplicationGroup(string name)
+ {
+ Name = name ?? throw new ArgumentNullException(nameof(name));
+ }
+
+ ///
+ /// Serialization constructor
+ ///
+ private CreateApplicationGroup()
+ {
+ }
+
+ ///
+ /// Name of the new group (human friendly name).
+ ///
+ public string Name { get; private set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Applications/Commands/DeleteApplication.cs b/src/Server/Coderr.Server.Api/Core/Applications/Commands/DeleteApplication.cs
similarity index 84%
rename from src/Server/OneTrueError.Api/Core/Applications/Commands/DeleteApplication.cs
rename to src/Server/Coderr.Server.Api/Core/Applications/Commands/DeleteApplication.cs
index 8c501e11..c6f391d2 100644
--- a/src/Server/OneTrueError.Api/Core/Applications/Commands/DeleteApplication.cs
+++ b/src/Server/Coderr.Server.Api/Core/Applications/Commands/DeleteApplication.cs
@@ -1,12 +1,12 @@
using System;
-using DotNetCqs;
-namespace OneTrueError.Api.Core.Applications.Commands
+namespace Coderr.Server.Api.Core.Applications.Commands
{
///
/// Delete an existing application including of all its data.
///
- public class DeleteApplication : Command
+ [Message]
+ public class DeleteApplication
{
///
/// Creates a new instance of .
diff --git a/src/Server/Coderr.Server.Api/Core/Applications/Commands/DeleteApplicationGroup.cs b/src/Server/Coderr.Server.Api/Core/Applications/Commands/DeleteApplicationGroup.cs
new file mode 100644
index 00000000..40029da2
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Applications/Commands/DeleteApplicationGroup.cs
@@ -0,0 +1,43 @@
+namespace Coderr.Server.Api.Core.Applications.Commands
+{
+ ///
+ /// Create an application group.
+ ///
+ ///
+ ///
+ /// Groups are used to group similar applications together.
+ ///
+ ///
+ [Command]
+ public class DeleteApplicationGroup
+ {
+ ///
+ /// Creates a new instance of the class.
+ ///
+ /// Group to delete
+ /// Move all applications to this group
+ public DeleteApplicationGroup(int groupId, int moveAppsToGroupId)
+ {
+ GroupId = groupId;
+ MoveAppsToGroupId = moveAppsToGroupId;
+ }
+
+ ///
+ /// Serialization constructor
+ ///
+ private DeleteApplicationGroup()
+ {
+ }
+
+ ///
+ /// Group to delete
+ ///
+ public int GroupId { get; private set; }
+
+ ///
+ /// Move all applications to this group
+ ///
+ public int MoveAppsToGroupId { get; private set; }
+
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Applications/Commands/MapApplicationsToGroup.cs b/src/Server/Coderr.Server.Api/Core/Applications/Commands/MapApplicationsToGroup.cs
new file mode 100644
index 00000000..0b4e660a
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Applications/Commands/MapApplicationsToGroup.cs
@@ -0,0 +1,31 @@
+using System;
+
+namespace Coderr.Server.Api.Core.Applications.Commands
+{
+ [Message]
+ public class MapApplicationsToGroup
+ {
+ public MapApplicationsToGroup(int groupId, int[] applicationIds)
+ {
+ if (applicationIds == null) throw new ArgumentNullException(nameof(applicationIds));
+ if (groupId <= 0) throw new ArgumentOutOfRangeException(nameof(groupId));
+ GroupId = groupId;
+ ApplicationIds = applicationIds ?? throw new ArgumentNullException(nameof(applicationIds));
+ }
+
+ protected MapApplicationsToGroup()
+ {
+
+ }
+
+ ///
+ /// Applications to assign to the group.
+ ///
+ public int[] ApplicationIds { get; private set; }
+
+ ///
+ /// Group that the applications should be assigned to.
+ ///
+ public int GroupId { get; private set; }
+ }
+}
diff --git a/src/Server/Coderr.Server.Api/Core/Applications/Commands/MuteStatisticsQuestion.cs b/src/Server/Coderr.Server.Api/Core/Applications/Commands/MuteStatisticsQuestion.cs
new file mode 100644
index 00000000..967f1433
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Applications/Commands/MuteStatisticsQuestion.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Coderr.Server.Api.Core.Applications.Commands
+{
+ ///
+ /// Do not pester the user with the question about adding info for statistics.
+ ///
+ [Command]
+ public class MuteStatisticsQuestion
+ {
+ public int ApplicationId { get; set; }
+ }
+}
diff --git a/src/Server/OneTrueError.Api/Core/Applications/Commands/RemoveTeamMember.cs b/src/Server/Coderr.Server.Api/Core/Applications/Commands/RemoveTeamMember.cs
similarity index 89%
rename from src/Server/OneTrueError.Api/Core/Applications/Commands/RemoveTeamMember.cs
rename to src/Server/Coderr.Server.Api/Core/Applications/Commands/RemoveTeamMember.cs
index 5a649553..e02fa687 100644
--- a/src/Server/OneTrueError.Api/Core/Applications/Commands/RemoveTeamMember.cs
+++ b/src/Server/Coderr.Server.Api/Core/Applications/Commands/RemoveTeamMember.cs
@@ -1,12 +1,12 @@
using System;
-using DotNetCqs;
-namespace OneTrueError.Api.Core.Applications.Commands
+namespace Coderr.Server.Api.Core.Applications.Commands
{
///
/// Remove a team member from the
///
- public class RemoveTeamMember : Command
+ [Message]
+ public class RemoveTeamMember
{
///
/// Creates a new instance of .
diff --git a/src/Server/Coderr.Server.Api/Core/Applications/Commands/RenameApplicationGroup.cs b/src/Server/Coderr.Server.Api/Core/Applications/Commands/RenameApplicationGroup.cs
new file mode 100644
index 00000000..0f52dbad
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Applications/Commands/RenameApplicationGroup.cs
@@ -0,0 +1,18 @@
+using System;
+
+namespace Coderr.Server.Api.Core.Applications.Commands
+{
+ [Message]
+ public class RenameApplicationGroup
+ {
+ public RenameApplicationGroup(int groupId, string newName)
+ {
+ if (groupId <= 0) throw new ArgumentOutOfRangeException(nameof(groupId));
+ GroupId = groupId;
+ NewName = newName ?? throw new ArgumentNullException(nameof(newName));
+ }
+
+ public int GroupId { get; private set; }
+ public string NewName { get; private set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Applications/Commands/SetApplicationGroup.cs b/src/Server/Coderr.Server.Api/Core/Applications/Commands/SetApplicationGroup.cs
new file mode 100644
index 00000000..be3532f6
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Applications/Commands/SetApplicationGroup.cs
@@ -0,0 +1,56 @@
+namespace Coderr.Server.Api.Core.Applications.Commands
+{
+ ///
+ /// Assign an application to a group.
+ ///
+ ///
+ ///
+ /// Groups are used to make it easier to navigate between applications.
+ ///
+ ///
+ [Command]
+ public class SetApplicationGroup
+ {
+ ///
+ /// Creates a new instance of the class.
+ ///
+ /// Application to assign a group to.
+ /// Group to assign the application to
+ public SetApplicationGroup(int applicationId, int applicationGroupId)
+ {
+ ApplicationId = applicationId;
+ ApplicationGroupId = applicationGroupId;
+ }
+
+ ///
+ /// Creates a new instance of the class.
+ ///
+ /// Application to assign a group to.
+ /// Group to assign the application to
+ public SetApplicationGroup(int applicationId, string groupName)
+ {
+ ApplicationId = applicationId;
+ GroupName = groupName;
+ }
+
+ protected SetApplicationGroup()
+ {
+
+ }
+
+ ///
+ /// Group to show the application under.
+ ///
+ public int ApplicationGroupId { get; private set; }
+
+ ///
+ /// Application which should appear under the group
+ ///
+ public int ApplicationId { get; private set; }
+
+ ///
+ /// Group name (you can specify either the group Id or the group name)
+ ///
+ public string GroupName { get; private set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Applications/Commands/UpdateApplication.cs b/src/Server/Coderr.Server.Api/Core/Applications/Commands/UpdateApplication.cs
similarity index 83%
rename from src/Server/OneTrueError.Api/Core/Applications/Commands/UpdateApplication.cs
rename to src/Server/Coderr.Server.Api/Core/Applications/Commands/UpdateApplication.cs
index 2c7043d2..4002c5cc 100644
--- a/src/Server/OneTrueError.Api/Core/Applications/Commands/UpdateApplication.cs
+++ b/src/Server/Coderr.Server.Api/Core/Applications/Commands/UpdateApplication.cs
@@ -1,12 +1,12 @@
using System;
-using DotNetCqs;
-namespace OneTrueError.Api.Core.Applications.Commands
+namespace Coderr.Server.Api.Core.Applications.Commands
{
///
/// Update application
///
- public class UpdateApplication : Command
+ [Message]
+ public class UpdateApplication
{
///
/// Creates a new instance of .
@@ -40,5 +40,10 @@ public UpdateApplication(int applicationId, string name)
///
///
public TypeOfApplication? TypeOfApplication { get; set; }
+
+ ///
+ /// Number of days to keep new incidents.
+ ///
+ public int? RetentionDays { get; set; }
}
}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Applications/Commands/UpdateRoles.cs b/src/Server/Coderr.Server.Api/Core/Applications/Commands/UpdateRoles.cs
new file mode 100644
index 00000000..ea86dceb
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Applications/Commands/UpdateRoles.cs
@@ -0,0 +1,11 @@
+namespace Coderr.Server.Api.Core.Applications.Commands
+{
+ [Command]
+ public class UpdateRoles
+ {
+ public int UserToUpdate { get; set; }
+ public int ApplicationId { get; set; }
+
+ public string[] Roles { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Applications/Events/ApplicationCreated.cs b/src/Server/Coderr.Server.Api/Core/Applications/Events/ApplicationCreated.cs
similarity index 92%
rename from src/Server/OneTrueError.Api/Core/Applications/Events/ApplicationCreated.cs
rename to src/Server/Coderr.Server.Api/Core/Applications/Events/ApplicationCreated.cs
index d900a9d7..fa4ba596 100644
--- a/src/Server/OneTrueError.Api/Core/Applications/Events/ApplicationCreated.cs
+++ b/src/Server/Coderr.Server.Api/Core/Applications/Events/ApplicationCreated.cs
@@ -1,67 +1,69 @@
-using System;
-using DotNetCqs;
-
-namespace OneTrueError.Api.Core.Applications.Events
-{
- ///
- /// Published when a new application have been created by a user.
- ///
- public class ApplicationCreated : ApplicationEvent
- {
- ///
- /// Creates a new instance of .
- ///
- /// application identity
- /// name as specified by the user
- /// account id for the user that created the application
- /// appKey used to identify the application during uploads.
- /// Used with to authenticate the upload.
- public ApplicationCreated(int id, string name, int createdById, string appKey, string sharedSecret)
- {
- if (name == null) throw new ArgumentNullException("name");
- if (appKey == null) throw new ArgumentNullException("appKey");
- if (sharedSecret == null) throw new ArgumentNullException("sharedSecret");
- if (id <= 0) throw new ArgumentOutOfRangeException("id");
- if (createdById <= 0) throw new ArgumentOutOfRangeException("createdById");
-
- CreatedById = createdById;
- AppKey = appKey;
- SharedSecret = sharedSecret;
- ApplicationId = id;
- ApplicationName = name;
- }
-
- ///
- /// Serialization constructor
- ///
- protected ApplicationCreated()
- {
- }
-
- ///
- /// Application key which is used to identify the application that uploads a report.
- ///
- public string AppKey { get; set; }
-
-
- ///
- /// Application identity
- ///
- public int ApplicationId { get; set; }
-
- ///
- /// Name as entered by the user.
- ///
- public string ApplicationName { get; private set; }
-
- ///
- /// Account id of the person that created this application
- ///
- public int CreatedById { get; private set; }
-
- ///
- /// Used together with the to be able to authenticate the upload.
- ///
- public string SharedSecret { get; set; }
- }
+using System;
+
+// ReSharper disable All
+
+namespace Coderr.Server.Api.Core.Applications.Events
+{
+ ///
+ /// Published when a new application have been created by a user.
+ ///
+ [Message]
+ public class ApplicationCreated
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// application identity
+ /// name as specified by the user
+ /// account id for the user that created the application
+ /// appKey used to identify the application during uploads.
+ /// Used with to authenticate the upload.
+ public ApplicationCreated(int id, string name, int createdById, string appKey, string sharedSecret)
+ {
+ if (name == null) throw new ArgumentNullException("name");
+ if (appKey == null) throw new ArgumentNullException("appKey");
+ if (sharedSecret == null) throw new ArgumentNullException("sharedSecret");
+ if (id <= 0) throw new ArgumentOutOfRangeException("id");
+ if (createdById <= 0) throw new ArgumentOutOfRangeException("createdById");
+
+ CreatedById = createdById;
+ AppKey = appKey;
+ SharedSecret = sharedSecret;
+ ApplicationId = id;
+ ApplicationName = name;
+ }
+
+ ///
+ /// Serialization constructor
+ ///
+ protected ApplicationCreated()
+ {
+ }
+
+ ///
+ /// Application key which is used to identify the application that uploads a report.
+ ///
+ public string AppKey { get; set; }
+
+
+ ///
+ /// Application identity
+ ///
+ public int ApplicationId { get; set; }
+
+ ///
+ /// Name as entered by the user.
+ ///
+ public string ApplicationName { get; private set; }
+
+ ///
+ /// Account id of the person that created this application
+ ///
+ public int CreatedById { get; private set; }
+
+ ///
+ /// Used together with the to be able to authenticate the upload.
+ ///
+ public string SharedSecret { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Applications/Events/ApplicationDeleted.cs b/src/Server/Coderr.Server.Api/Core/Applications/Events/ApplicationDeleted.cs
similarity index 79%
rename from src/Server/OneTrueError.Api/Core/Applications/Events/ApplicationDeleted.cs
rename to src/Server/Coderr.Server.Api/Core/Applications/Events/ApplicationDeleted.cs
index 90012346..b9fbfdc2 100644
--- a/src/Server/OneTrueError.Api/Core/Applications/Events/ApplicationDeleted.cs
+++ b/src/Server/Coderr.Server.Api/Core/Applications/Events/ApplicationDeleted.cs
@@ -1,11 +1,10 @@
-using DotNetCqs;
-
-namespace OneTrueError.Api.Core.Applications.Events
+namespace Coderr.Server.Api.Core.Applications.Events
{
///
/// An application have been deleted.
///
- public class ApplicationDeleted : ApplicationEvent
+ [Message]
+ public class ApplicationDeleted
{
///
/// Key used when uploading reports
diff --git a/src/Server/Coderr.Server.Api/Core/Applications/Events/ApplicationGroupCreated.cs b/src/Server/Coderr.Server.Api/Core/Applications/Events/ApplicationGroupCreated.cs
new file mode 100644
index 00000000..e45acae0
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Applications/Events/ApplicationGroupCreated.cs
@@ -0,0 +1,21 @@
+namespace Coderr.Server.Api.Core.Applications.Events
+{
+ public class ApplicationGroupCreated
+ {
+ public ApplicationGroupCreated(int id, string name, int createdById)
+ {
+ Id = id;
+ Name = name;
+ CreatedById = createdById;
+ }
+
+ protected ApplicationGroupCreated()
+ {
+
+ }
+
+ public int CreatedById { get; private set; }
+ public int Id { get; private set; }
+ public string Name { get; private set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Applications/Events/UserAddedToApplication.cs b/src/Server/Coderr.Server.Api/Core/Applications/Events/UserAddedToApplication.cs
new file mode 100644
index 00000000..e45a15d4
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Applications/Events/UserAddedToApplication.cs
@@ -0,0 +1,37 @@
+namespace Coderr.Server.Api.Core.Applications.Events
+{
+ ///
+ /// A user have been added directly, or through an invitation
+ ///
+ [Message]
+ public class UserAddedToApplication
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// Identifier for the application that the user was added to.
+ /// Account identifier for the user that was added to the application
+ public UserAddedToApplication(int applicationId, int accountId)
+ {
+ ApplicationId = applicationId;
+ AccountId = accountId;
+ }
+
+ ///
+ /// Serialization constructor
+ ///
+ protected UserAddedToApplication()
+ {
+ }
+
+ ///
+ /// Account identifier for the user that was added to the application
+ ///
+ public int AccountId { get; private set; }
+
+ ///
+ /// Identifier for the application that the user was added to.
+ ///
+ public int ApplicationId { get; private set; }
+ }
+}
diff --git a/src/Server/OneTrueError.Api/Core/Applications/Events/UserInvitedToApplication.cs b/src/Server/Coderr.Server.Api/Core/Applications/Events/UserInvitedToApplication.cs
similarity index 91%
rename from src/Server/OneTrueError.Api/Core/Applications/Events/UserInvitedToApplication.cs
rename to src/Server/Coderr.Server.Api/Core/Applications/Events/UserInvitedToApplication.cs
index 555e3c1e..ea6b2cd3 100644
--- a/src/Server/OneTrueError.Api/Core/Applications/Events/UserInvitedToApplication.cs
+++ b/src/Server/Coderr.Server.Api/Core/Applications/Events/UserInvitedToApplication.cs
@@ -1,68 +1,68 @@
-using System;
-using DotNetCqs;
-using OneTrueError.Api.Core.Invitations.Commands;
-
-namespace OneTrueError.Api.Core.Applications.Events
-{
- ///
- /// Event published when the command is done.
- ///
- public class UserInvitedToApplication : ApplicationEvent
- {
- ///
- /// Creates a new instance of .
- ///
- /// Key that the user clicks on in the invitation email
- /// Application that the user was invited to
- /// application name
- /// Email address that the invitation was sent to
- /// Username for the user that made the invitation
- /// emailAddress; invitedBy
- /// applicationId
- public UserInvitedToApplication(string invitationKey, int applicationId, string applicationName,
- string emailAddress, string invitedBy)
- {
- if (invitationKey == null) throw new ArgumentNullException("invitationKey");
- if (emailAddress == null) throw new ArgumentNullException("emailAddress");
- if (invitedBy == null) throw new ArgumentNullException("invitedBy");
- if (applicationId <= 0) throw new ArgumentOutOfRangeException("applicationId");
- InvitationKey = invitationKey;
- ApplicationId = applicationId;
- ApplicationName = applicationName;
- EmailAddress = emailAddress;
- InvitedBy = invitedBy;
- }
-
- ///
- /// Serialization constructor
- ///
- protected UserInvitedToApplication()
- {
- }
-
- ///
- /// Application that the user will gain access to.
- ///
- public int ApplicationId { get; private set; }
-
- ///
- /// Application name
- ///
- public string ApplicationName { get; private set; }
-
- ///
- /// Email address to the invited user.
- ///
- public string EmailAddress { get; private set; }
-
- ///
- /// Identifier sent in the invitation email.
- ///
- public string InvitationKey { get; private set; }
-
- ///
- /// Username of the user that invited the other user.
- ///
- public string InvitedBy { get; private set; }
- }
+using System;
+using Coderr.Server.Api.Core.Invitations.Commands;
+
+namespace Coderr.Server.Api.Core.Applications.Events
+{
+ ///
+ /// Event published when the command is done.
+ ///
+ [Message]
+ public class UserInvitedToApplication
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// Key that the user clicks on in the invitation email
+ /// Application that the user was invited to
+ /// application name
+ /// Email address that the invitation was sent to
+ /// Username for the user that made the invitation
+ /// emailAddress; invitedBy
+ /// applicationId
+ public UserInvitedToApplication(string invitationKey, int applicationId, string applicationName,
+ string emailAddress, string invitedBy)
+ {
+ if (invitationKey == null) throw new ArgumentNullException("invitationKey");
+ if (emailAddress == null) throw new ArgumentNullException("emailAddress");
+ if (invitedBy == null) throw new ArgumentNullException("invitedBy");
+ if (applicationId <= 0) throw new ArgumentOutOfRangeException("applicationId");
+ InvitationKey = invitationKey;
+ ApplicationId = applicationId;
+ ApplicationName = applicationName;
+ EmailAddress = emailAddress;
+ InvitedBy = invitedBy;
+ }
+
+ ///
+ /// Serialization constructor
+ ///
+ protected UserInvitedToApplication()
+ {
+ }
+
+ ///
+ /// Application that the user will gain access to.
+ ///
+ public int ApplicationId { get; private set; }
+
+ ///
+ /// Application name
+ ///
+ public string ApplicationName { get; private set; }
+
+ ///
+ /// Email address to the invited user.
+ ///
+ public string EmailAddress { get; private set; }
+
+ ///
+ /// Identifier sent in the invitation email.
+ ///
+ public string InvitationKey { get; private set; }
+
+ ///
+ /// Username of the user that invited the other user.
+ ///
+ public string InvitedBy { get; private set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Applications/NamespaceDoc.cs b/src/Server/Coderr.Server.Api/Core/Applications/NamespaceDoc.cs
new file mode 100644
index 00000000..0c3dd6b3
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Applications/NamespaceDoc.cs
@@ -0,0 +1,20 @@
+using System.Runtime.CompilerServices;
+
+namespace Coderr.Server.Api.Core.Applications
+{
+ // This file is Generated by the tool MarkdownToNamespaceDoc. ReadMe.md is the master.
+
+ ///
+ /// An application that we can receive exceptions for.
+ ///
+ ///
+ ///
+ /// It can also be a specific tier in an application. For instance ASP.NET WebApi, or client side (like an Mobile
+ /// application).
+ ///
+ ///
+ [CompilerGenerated]
+ internal class NamespaceDoc
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationGroupMap.cs b/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationGroupMap.cs
new file mode 100644
index 00000000..dc832b03
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationGroupMap.cs
@@ -0,0 +1,10 @@
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Core.Applications.Queries
+{
+ [Message]
+ public class GetApplicationGroupMap : Query
+ {
+ public int? ApplicationId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationGroupMapResult.cs b/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationGroupMapResult.cs
new file mode 100644
index 00000000..471a66ee
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationGroupMapResult.cs
@@ -0,0 +1,10 @@
+namespace Coderr.Server.Api.Core.Applications.Queries
+{
+ public class GetApplicationGroupMapResult
+ {
+ ///
+ /// If application id was specified, this will only contain one item; otherwise all maps.
+ ///
+ public GetApplicationGroupMapResultItem[] Items { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationGroupMapResultItem.cs b/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationGroupMapResultItem.cs
new file mode 100644
index 00000000..bb03f499
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationGroupMapResultItem.cs
@@ -0,0 +1,8 @@
+namespace Coderr.Server.Api.Core.Applications.Queries
+{
+ public class GetApplicationGroupMapResultItem
+ {
+ public int ApplicationId { get; set; }
+ public int GroupId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationGroups.cs b/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationGroups.cs
new file mode 100644
index 00000000..9ad4bfbb
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationGroups.cs
@@ -0,0 +1,9 @@
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Core.Applications.Queries
+{
+ [Message]
+ public class GetApplicationGroups : Query
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationGroupsResult.cs b/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationGroupsResult.cs
new file mode 100644
index 00000000..ea64c085
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationGroupsResult.cs
@@ -0,0 +1,7 @@
+namespace Coderr.Server.Api.Core.Applications.Queries
+{
+ public class GetApplicationGroupsResult
+ {
+ public GetApplicationGroupsResultItem[] Items { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationGroupsResultItem.cs b/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationGroupsResultItem.cs
new file mode 100644
index 00000000..622fa70f
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationGroupsResultItem.cs
@@ -0,0 +1,9 @@
+namespace Coderr.Server.Api.Core.Applications.Queries
+{
+ public class GetApplicationGroupsResultItem
+ {
+ public int Id { get; set; }
+ public string Name { get; set; }
+ public int[] ApplicationIds { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Applications/Queries/GetApplicationIdByKey.cs b/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationIdByKey.cs
similarity index 92%
rename from src/Server/OneTrueError.Api/Core/Applications/Queries/GetApplicationIdByKey.cs
rename to src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationIdByKey.cs
index 0f850351..f24ce9c7 100644
--- a/src/Server/OneTrueError.Api/Core/Applications/Queries/GetApplicationIdByKey.cs
+++ b/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationIdByKey.cs
@@ -1,36 +1,37 @@
-using System;
-using DotNetCqs;
-
-namespace OneTrueError.Api.Core.Applications.Queries
-{
- ///
- /// Get an application by using the AppKey.
- ///
- public class GetApplicationIdByKey : Query
- {
- ///
- /// Creates a new instance of .
- ///
- /// appKey (GUID)
- public GetApplicationIdByKey(string applicationKey)
- {
- if (applicationKey == null) throw new ArgumentNullException("applicationKey");
- Guid uid;
- if (!Guid.TryParse(applicationKey, out uid))
- throw new FormatException("'" + applicationKey + "' is not a valid application key.");
- ApplicationKey = applicationKey;
- }
-
- ///
- /// Serialization constructor
- ///
- protected GetApplicationIdByKey()
- {
- }
-
- ///
- /// AppKey
- ///
- public string ApplicationKey { get; private set; }
- }
+using System;
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Core.Applications.Queries
+{
+ ///
+ /// Get an application by using the AppKey.
+ ///
+ [Message]
+ public class GetApplicationIdByKey : Query
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// appKey (GUID)
+ public GetApplicationIdByKey(string applicationKey)
+ {
+ if (applicationKey == null) throw new ArgumentNullException("applicationKey");
+ Guid uid;
+ if (!Guid.TryParse(applicationKey, out uid))
+ throw new FormatException("'" + applicationKey + "' is not a valid application key.");
+ ApplicationKey = applicationKey;
+ }
+
+ ///
+ /// Serialization constructor
+ ///
+ protected GetApplicationIdByKey()
+ {
+ }
+
+ ///
+ /// AppKey
+ ///
+ public string ApplicationKey { get; private set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Applications/Queries/GetApplicationIdByKeyResult.cs b/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationIdByKeyResult.cs
similarity index 80%
rename from src/Server/OneTrueError.Api/Core/Applications/Queries/GetApplicationIdByKeyResult.cs
rename to src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationIdByKeyResult.cs
index 53421366..6e57336e 100644
--- a/src/Server/OneTrueError.Api/Core/Applications/Queries/GetApplicationIdByKeyResult.cs
+++ b/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationIdByKeyResult.cs
@@ -1,13 +1,13 @@
-namespace OneTrueError.Api.Core.Applications.Queries
-{
- ///
- /// Result for .
- ///
- public class GetApplicationIdByKeyResult
- {
- ///
- /// Application id
- ///
- public int Id { get; set; }
- }
+namespace Coderr.Server.Api.Core.Applications.Queries
+{
+ ///
+ /// Result for .
+ ///
+ public class GetApplicationIdByKeyResult
+ {
+ ///
+ /// Application id
+ ///
+ public int Id { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Applications/Queries/GetApplicationInfo.cs b/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationInfo.cs
similarity index 93%
rename from src/Server/OneTrueError.Api/Core/Applications/Queries/GetApplicationInfo.cs
rename to src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationInfo.cs
index 6e2c4a1a..03f39724 100644
--- a/src/Server/OneTrueError.Api/Core/Applications/Queries/GetApplicationInfo.cs
+++ b/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationInfo.cs
@@ -1,73 +1,75 @@
-using System;
-using DotNetCqs;
-
-namespace OneTrueError.Api.Core.Applications.Queries
-{
- ///
- /// Get information for an application either by using the key or application id
- ///
- public class GetApplicationInfo : Query
- {
- private string _appKey;
- private int _applicationId;
-
- ///
- /// Creates a new instance of .
- ///
- /// identity of the application
- public GetApplicationInfo(int id)
- {
- if (id <= 0) throw new ArgumentOutOfRangeException("id");
- ApplicationId = id;
- }
-
- ///
- /// Creates a new instance of .
- ///
- /// Application key used when sending error reports
- public GetApplicationInfo(string appKey)
- {
- if (appKey == null) throw new ArgumentNullException("appKey");
- AppKey = appKey;
- }
-
- ///
- /// Creates a new instance of .
- ///
- protected GetApplicationInfo()
- {
- }
-
- ///
- /// Application key from the user interface
- ///
- /// Not a valid application key.
- public string AppKey
- {
- get { return _appKey; }
- set
- {
- Guid uid;
- if (!Guid.TryParse(value, out uid))
- throw new FormatException("'" + value + "' is not a valid application key.");
-
- _appKey = value;
- }
- }
-
- ///
- /// Application id
- ///
- /// Not a valid application id
- public int ApplicationId
- {
- get { return _applicationId; }
- set
- {
- if (value <= 0)
- throw new ArgumentOutOfRangeException("value", value, "Not a valid id.");
- _applicationId = value;
- }
- }
- }
+using System;
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Core.Applications.Queries
+{
+ ///
+ /// Get information for an application either by using the key or application id
+ ///
+ [Message]
+ public class GetApplicationInfo : Query
+ {
+ private string _appKey;
+ private int _applicationId;
+
+ ///
+ /// Creates a new instance of .
+ ///
+ /// identity of the application
+ public GetApplicationInfo(int id)
+ {
+ if (id <= 0) throw new ArgumentOutOfRangeException("id");
+ ApplicationId = id;
+ }
+
+ ///
+ /// Creates a new instance of .
+ ///
+ /// Application key used when sending error reports
+ public GetApplicationInfo(string appKey)
+ {
+ if (appKey == null) throw new ArgumentNullException("appKey");
+ AppKey = appKey;
+ }
+
+ ///
+ /// Creates a new instance of .
+ ///
+ protected GetApplicationInfo()
+ {
+ }
+
+ ///
+ /// Application key from the user interface
+ ///
+ /// Not a valid application key.
+ public string AppKey
+ {
+ get { return _appKey; }
+ set
+ {
+ Guid uid;
+ if (!Guid.TryParse(value, out uid))
+ throw new FormatException("'" + value + "' is not a valid application key.");
+
+ _appKey = value;
+ }
+ }
+
+ ///
+ /// Application id
+ ///
+ /// Not a valid application id
+ public int ApplicationId
+ {
+ get { return _applicationId; }
+ set
+ {
+ // Will be 0 when appKey is specified.
+ if (value < 0)
+ throw new ArgumentOutOfRangeException("value", value, "Not a valid id.");
+ _applicationId = value;
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationInfoResult.cs b/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationInfoResult.cs
new file mode 100644
index 00000000..996c842c
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationInfoResult.cs
@@ -0,0 +1,75 @@
+using System;
+
+namespace Coderr.Server.Api.Core.Applications.Queries
+{
+ ///
+ /// Result for .
+ ///
+ public class GetApplicationInfoResult
+ {
+ ///
+ /// Application key
+ ///
+ public string AppKey { get; set; }
+
+ ///
+ /// Type of application
+ ///
+ public TypeOfApplication ApplicationType { get; set; }
+
+ ///
+ /// Application id
+ ///
+ public int Id { get; set; }
+
+ ///
+ /// Name of the application.
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// Shared secret, used together with to make sure that the reports come from the correct source.
+ ///
+ public string SharedSecret { get; set; }
+
+ ///
+ /// Total number of incidents for this application.
+ ///
+ public int TotalIncidentCount { get; set; }
+
+ ///
+ /// Number of full time developers working on this application (1.5 = one full time and one half time)
+ ///
+ ///
+ ///
+ ///null = not specified
+ ///
+ ///
+ public decimal? NumberOfDevelopers { get; set; }
+
+ ///
+ /// Versions that we have received error reports for.
+ ///
+ public string[] Versions { get; set; }
+
+ ///
+ /// Got information to be able to compare how the team is performing with other teams.
+ ///
+ public bool ShowStatsQuestion { get; set; }
+
+ ///
+ /// Number of days to keep new incidents before deleting them.
+ ///
+ ///
+ ///
+ /// We've seen that errors that aren't within 60 days aren't fixed at all. It's therefore better to delete them than to keep them in the system (and adding noise to the error list).
+ ///
+ ///
+ public int RetentionDays { get; set; }
+
+ ///
+ /// When we received the last incident.
+ ///
+ public DateTime? LastIncidentAtUtc { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Applications/Queries/GetApplicationList.cs b/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationList.cs
similarity index 89%
rename from src/Server/OneTrueError.Api/Core/Applications/Queries/GetApplicationList.cs
rename to src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationList.cs
index 101b28c7..1dc4c4df 100644
--- a/src/Server/OneTrueError.Api/Core/Applications/Queries/GetApplicationList.cs
+++ b/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationList.cs
@@ -1,25 +1,26 @@
-using DotNetCqs;
-
-namespace OneTrueError.Api.Core.Applications.Queries
-{
- ///
- /// Get a list of applications.
- ///
- public class GetApplicationList : Query
- {
- ///
- /// Get all applications that the given user have access to
- ///
- ///
- ///
- /// 0 = get all applications
- ///
- ///
- public int AccountId { get; set; }
-
- ///
- /// Only list applications that the given account is administrator for.
- ///
- public bool FilterAsAdmin { get; set; }
- }
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Core.Applications.Queries
+{
+ ///
+ /// Get a list of applications.
+ ///
+ [Message]
+ public class GetApplicationList : Query
+ {
+ ///
+ /// Get all applications that the given user have access to
+ ///
+ ///
+ ///
+ /// 0 = get all applications
+ ///
+ ///
+ public int AccountId { get; set; }
+
+ ///
+ /// Only list applications that the given account is administrator for.
+ ///
+ public bool FilterAsAdmin { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationOverview.cs b/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationOverview.cs
new file mode 100644
index 00000000..fe0840dd
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationOverview.cs
@@ -0,0 +1,58 @@
+using System;
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Core.Applications.Queries
+{
+ ///
+ /// Get stats etc that can be presented as an overview for an application.
+ ///
+ [Message]
+ public class GetApplicationOverview : Query
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ ///
+ /// applicationId
+ public GetApplicationOverview(int applicationId)
+ {
+ if (applicationId <= 0) throw new ArgumentOutOfRangeException("applicationId");
+ ApplicationId = applicationId;
+ }
+
+ ///
+ /// Serialization constructor
+ ///
+ protected GetApplicationOverview()
+ {
+ }
+
+ ///
+ /// Application id to get an overview for.
+ ///
+ public int ApplicationId { get; private set; }
+
+ ///
+ /// Amount of time to look back (i.e. startdate = DateTime.Now.Substract(WindowSize))
+ ///
+ ///
+ /// 1 = switch to hours
+ ///
+ public int NumberOfDays { get; set; }
+
+ ///
+ /// Filter on a specific version ("1.1.0")
+ ///
+ public string Version { get; set; }
+
+ ///
+ /// Load chart data.
+ ///
+ public bool IncludeChartData { get; set; } = true;
+
+ ///
+ /// Include summary count per partition.
+ ///
+ public bool IncludePartitions { get; set; } = false;
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Applications/Queries/GetApplicationOverviewResult.cs b/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationOverviewResult.cs
similarity index 90%
rename from src/Server/OneTrueError.Api/Core/Applications/Queries/GetApplicationOverviewResult.cs
rename to src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationOverviewResult.cs
index e37f6f9f..03d055de 100644
--- a/src/Server/OneTrueError.Api/Core/Applications/Queries/GetApplicationOverviewResult.cs
+++ b/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationOverviewResult.cs
@@ -1,34 +1,34 @@
-namespace OneTrueError.Api.Core.Applications.Queries
-{
- ///
- /// Result for .
- ///
- //TODO, move to the web namespace.
- public class GetApplicationOverviewResult
- {
- ///
- /// 1 = switch to hours for incidents and reports.
- ///
- public int Days { get; set; }
-
- ///
- /// One entry for each day
- ///
- public int[] ErrorReports { get; set; }
-
- ///
- /// One incident count for each day
- ///
- public int[] Incidents { get; set; }
-
- ///
- /// Statistics summary
- ///
- public OverviewStatSummary StatSummary { get; set; }
-
- ///
- /// Labels for X axis
- ///
- public string[] TimeAxisLabels { get; set; }
- }
+namespace Coderr.Server.Api.Core.Applications.Queries
+{
+ ///
+ /// Result for .
+ ///
+ //TODO, move to the web namespace.
+ public class GetApplicationOverviewResult
+ {
+ ///
+ /// 1 = switch to hours for incidents and reports.
+ ///
+ public int Days { get; set; }
+
+ ///
+ /// One entry for each day
+ ///
+ public int[] ErrorReports { get; set; }
+
+ ///
+ /// One incident count for each day
+ ///
+ public int[] Incidents { get; set; }
+
+ ///
+ /// Statistics summary
+ ///
+ public OverviewStatSummary StatSummary { get; set; }
+
+ ///
+ /// Labels for X axis
+ ///
+ public string[] TimeAxisLabels { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Applications/Queries/GetApplicationTeam.cs b/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationTeam.cs
similarity index 91%
rename from src/Server/OneTrueError.Api/Core/Applications/Queries/GetApplicationTeam.cs
rename to src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationTeam.cs
index 9de2d91f..6037aac6 100644
--- a/src/Server/OneTrueError.Api/Core/Applications/Queries/GetApplicationTeam.cs
+++ b/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationTeam.cs
@@ -1,34 +1,35 @@
-using System;
-using DotNetCqs;
-
-namespace OneTrueError.Api.Core.Applications.Queries
-{
- ///
- /// Get all members of a specific application
- ///
- public class GetApplicationTeam : Query
- {
- ///
- /// Creates a new instance of .
- ///
- /// application id
- /// applicationId
- public GetApplicationTeam(int applicationId)
- {
- if (applicationId <= 0) throw new ArgumentOutOfRangeException("applicationId");
- ApplicationId = applicationId;
- }
-
- ///
- /// Serialization constructor
- ///
- protected GetApplicationTeam()
- {
- }
-
- ///
- /// Application id
- ///
- public int ApplicationId { get; private set; }
- }
+using System;
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Core.Applications.Queries
+{
+ ///
+ /// Get all members of a specific application
+ ///
+ [Message]
+ public class GetApplicationTeam : Query
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// application id
+ /// applicationId
+ public GetApplicationTeam(int applicationId)
+ {
+ if (applicationId <= 0) throw new ArgumentOutOfRangeException("applicationId");
+ ApplicationId = applicationId;
+ }
+
+ ///
+ /// Serialization constructor
+ ///
+ protected GetApplicationTeam()
+ {
+ }
+
+ ///
+ /// Application id
+ ///
+ public int ApplicationId { get; private set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Applications/Queries/GetApplicationTeamMember.cs b/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationTeamMember.cs
similarity index 86%
rename from src/Server/OneTrueError.Api/Core/Applications/Queries/GetApplicationTeamMember.cs
rename to src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationTeamMember.cs
index 199f18af..9a56ba6a 100644
--- a/src/Server/OneTrueError.Api/Core/Applications/Queries/GetApplicationTeamMember.cs
+++ b/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationTeamMember.cs
@@ -1,25 +1,27 @@
-using System;
-
-namespace OneTrueError.Api.Core.Applications.Queries
-{
- ///
- /// Item for .
- ///
- public class GetApplicationTeamMember
- {
- ///
- /// When this person was added to the application (or rather when he accepted the invitation)
- ///
- public DateTime JoinedAtUtc { get; set; }
-
- ///
- /// Account id
- ///
- public int UserId { get; set; }
-
- ///
- /// Account name
- ///
- public string UserName { get; set; }
- }
+using System;
+
+namespace Coderr.Server.Api.Core.Applications.Queries
+{
+ ///
+ /// Item for .
+ ///
+ public class GetApplicationTeamMember
+ {
+ ///
+ /// When this person was added to the application (or rather when he accepted the invitation)
+ ///
+ public DateTime JoinedAtUtc { get; set; }
+
+ ///
+ /// Account id
+ ///
+ public int UserId { get; set; }
+
+ ///
+ /// Account name
+ ///
+ public string UserName { get; set; }
+
+ public bool IsAdmin { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Applications/Queries/GetApplicationTeamResult.cs b/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationTeamResult.cs
similarity index 86%
rename from src/Server/OneTrueError.Api/Core/Applications/Queries/GetApplicationTeamResult.cs
rename to src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationTeamResult.cs
index c3b96068..d03dd166 100644
--- a/src/Server/OneTrueError.Api/Core/Applications/Queries/GetApplicationTeamResult.cs
+++ b/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationTeamResult.cs
@@ -1,18 +1,18 @@
-namespace OneTrueError.Api.Core.Applications.Queries
-{
- ///
- /// Result for .
- ///
- public class GetApplicationTeamResult
- {
- ///
- /// Invited which have not yet accepted the invitation.
- ///
- public GetApplicationTeamResultInvitation[] Invited { get; set; }
-
- ///
- /// Members
- ///
- public GetApplicationTeamMember[] Members { get; set; }
- }
+namespace Coderr.Server.Api.Core.Applications.Queries
+{
+ ///
+ /// Result for .
+ ///
+ public class GetApplicationTeamResult
+ {
+ ///
+ /// Invited which have not yet accepted the invitation.
+ ///
+ public GetApplicationTeamResultInvitation[] Invited { get; set; }
+
+ ///
+ /// Members
+ ///
+ public GetApplicationTeamMember[] Members { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Applications/Queries/GetApplicationTeamResultInvitation.cs b/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationTeamResultInvitation.cs
similarity index 89%
rename from src/Server/OneTrueError.Api/Core/Applications/Queries/GetApplicationTeamResultInvitation.cs
rename to src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationTeamResultInvitation.cs
index 114f6d53..70ba1d70 100644
--- a/src/Server/OneTrueError.Api/Core/Applications/Queries/GetApplicationTeamResultInvitation.cs
+++ b/src/Server/Coderr.Server.Api/Core/Applications/Queries/GetApplicationTeamResultInvitation.cs
@@ -1,25 +1,25 @@
-using System;
-
-namespace OneTrueError.Api.Core.Applications.Queries
-{
- ///
- /// Item for .
- ///
- public class GetApplicationTeamResultInvitation
- {
- ///
- /// Address that the invitation was sent to.
- ///
- public string EmailAddress { get; set; }
-
- ///
- /// When the invitation was sent.
- ///
- public DateTime InvitedAtUtc { get; set; }
-
- ///
- /// User that sent the invitation.
- ///
- public string InvitedByUserName { get; set; }
- }
+using System;
+
+namespace Coderr.Server.Api.Core.Applications.Queries
+{
+ ///
+ /// Item for .
+ ///
+ public class GetApplicationTeamResultInvitation
+ {
+ ///
+ /// Address that the invitation was sent to.
+ ///
+ public string EmailAddress { get; set; }
+
+ ///
+ /// When the invitation was sent.
+ ///
+ public DateTime InvitedAtUtc { get; set; }
+
+ ///
+ /// User that sent the invitation.
+ ///
+ public string InvitedByUserName { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Applications/Queries/OverviewStatSummary.cs b/src/Server/Coderr.Server.Api/Core/Applications/Queries/OverviewStatSummary.cs
new file mode 100644
index 00000000..51aca3bb
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Applications/Queries/OverviewStatSummary.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+
+namespace Coderr.Server.Api.Core.Applications.Queries
+{
+ ///
+ /// Stats for the last seven days
+ ///
+ public class OverviewStatSummary
+ {
+ ///
+ /// Number of followers
+ ///
+ public int Followers { get; set; }
+
+ ///
+ /// Number of incidents
+ ///
+ public int Incidents { get; set; }
+
+ ///
+ /// Number of reports received
+ ///
+ public int Reports { get; set; }
+
+ ///
+ /// Number user feedback items
+ ///
+ public int UserFeedback { get; set; }
+
+
+ ///
+ /// Summary per partition
+ ///
+ public PartitionOverview[] Partitions { get; set; }
+
+ public DateTime? NewestIncidentReceivedAtUtc { get; set; }
+
+ public DateTime? NewestReportReceivedAtUtc { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Applications/Queries/PartitionOverview.cs b/src/Server/Coderr.Server.Api/Core/Applications/Queries/PartitionOverview.cs
new file mode 100644
index 00000000..80d7a9b0
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Applications/Queries/PartitionOverview.cs
@@ -0,0 +1,23 @@
+namespace Coderr.Server.Api.Core.Applications.Queries
+{
+ ///
+ /// Summary for a partition
+ ///
+ public class PartitionOverview
+ {
+ ///
+ /// Name, used when reporting errors.
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// Name to show for users.
+ ///
+ public string DisplayName { get; set; }
+
+ ///
+ /// Amount of unique values for this partition.
+ ///
+ public int Value { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Applications/ReadMe.md b/src/Server/Coderr.Server.Api/Core/Applications/ReadMe.md
similarity index 100%
rename from src/Server/OneTrueError.Api/Core/Applications/ReadMe.md
rename to src/Server/Coderr.Server.Api/Core/Applications/ReadMe.md
diff --git a/src/Server/Coderr.Server.Api/Core/Applications/TypeOfApplication.cs b/src/Server/Coderr.Server.Api/Core/Applications/TypeOfApplication.cs
new file mode 100644
index 00000000..2e59126f
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Applications/TypeOfApplication.cs
@@ -0,0 +1,38 @@
+namespace Coderr.Server.Api.Core.Applications
+{
+ ///
+ /// Kind of application that this is
+ ///
+ ///
+ ///
+ /// Used to determine how different analytics should be made, like analyzing memory usage (which has to guess the
+ /// total amount of memory if not included as context information).
+ ///
+ ///
+ /// For instance a OutOfMemoryException isn't as fatal in a mobile application, like it is in a large server
+ /// application, as the latter is supposed to have large amount of resources.
+ ///
+ ///
+ public enum TypeOfApplication
+ {
+ ///
+ /// Cellphone application
+ ///
+ ///
+ ///
+ /// An application with limited system resources (memory and usage).
+ ///
+ ///
+ Mobile,
+
+ ///
+ /// DesktopApplication application (i.e. a windows end user computer)
+ ///
+ DesktopApplication,
+
+ ///
+ /// Server, as a web server or a WCF service.
+ ///
+ Server
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Environments/Commands/CreateEnvironment.cs b/src/Server/Coderr.Server.Api/Core/Environments/Commands/CreateEnvironment.cs
new file mode 100644
index 00000000..b0e81466
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Environments/Commands/CreateEnvironment.cs
@@ -0,0 +1,41 @@
+using System;
+
+namespace Coderr.Server.Api.Core.Environments.Commands
+{
+ ///
+ /// Create an environment.
+ ///
+ [Command]
+ public class CreateEnvironment
+ {
+ public CreateEnvironment(int applicationId, string name)
+ {
+ if (applicationId <= 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(applicationId));
+ }
+
+ ApplicationId = applicationId;
+ Name = name ?? throw new ArgumentNullException(nameof(name));
+ }
+
+ protected CreateEnvironment()
+ {
+ }
+
+ ///
+ /// Application that the environment belongs to.
+ ///
+ public int ApplicationId { get; private set; }
+
+ ///
+ /// Do not track incidents in this environment.
+ ///
+ public bool DeleteIncidents { get; set; }
+
+ ///
+ /// Name used when reporting errors using the client library.
+ ///
+ public string Name { get; private set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Environments/Commands/ResetEnvironment.cs b/src/Server/Coderr.Server.Api/Core/Environments/Commands/ResetEnvironment.cs
new file mode 100644
index 00000000..d3f27c3f
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Environments/Commands/ResetEnvironment.cs
@@ -0,0 +1,32 @@
+using System;
+using Coderr.Server.Api.Core.Environments.Queries;
+
+namespace Coderr.Server.Api.Core.Environments.Commands
+{
+ ///
+ /// Delete all incidents in a specific environment
+ ///
+ [Command]
+ public class ResetEnvironment
+ {
+ public ResetEnvironment(int applicationId, int environmentId)
+ {
+ if (applicationId <= 0) throw new ArgumentOutOfRangeException(nameof(applicationId));
+ if (environmentId <= 0) throw new ArgumentOutOfRangeException(nameof(environmentId));
+
+ ApplicationId = applicationId;
+ EnvironmentId = environmentId;
+ }
+
+ protected ResetEnvironment()
+ {
+ }
+
+ public int ApplicationId { get; private set; }
+
+ ///
+ /// Environment to reset. Id comes from .
+ ///
+ public int EnvironmentId { get; private set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Environments/Commands/UpdateEnvironment.cs b/src/Server/Coderr.Server.Api/Core/Environments/Commands/UpdateEnvironment.cs
new file mode 100644
index 00000000..4a965659
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Environments/Commands/UpdateEnvironment.cs
@@ -0,0 +1,44 @@
+using System;
+using Coderr.Server.Api.Core.Environments.Queries;
+
+namespace Coderr.Server.Api.Core.Environments.Commands
+{
+ ///
+ /// Update an environment.
+ ///
+ [Command]
+ public class UpdateEnvironment
+ {
+ public UpdateEnvironment(int applicationId, int environmentId)
+ {
+ if (applicationId <= 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(applicationId));
+ }
+
+ if (environmentId <= 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(environmentId));
+ }
+
+ ApplicationId = applicationId;
+ EnvironmentId = environmentId;
+ }
+
+ protected UpdateEnvironment()
+ {
+ }
+
+ public int ApplicationId { get; private set; }
+
+ ///
+ /// Do not track incidents in this environment.
+ ///
+ public bool DeleteIncidents { get; set; }
+
+ ///
+ /// Environment to reset. Id comes from .
+ ///
+ public int EnvironmentId { get; private set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Environments/Queries/GetEnvironments.cs b/src/Server/Coderr.Server.Api/Core/Environments/Queries/GetEnvironments.cs
new file mode 100644
index 00000000..3ce27570
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Environments/Queries/GetEnvironments.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Core.Environments.Queries
+{
+ ///
+ /// Get all environments that we've received error reports in
+ ///
+ [Message]
+ public class GetEnvironments : Query
+ {
+ public GetEnvironments(int applicationId)
+ {
+ if (applicationId <= 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(applicationId));
+ }
+
+ ApplicationId = applicationId;
+ }
+
+ protected GetEnvironments()
+ {
+
+ }
+
+ ///
+ /// Fetch all environments for a specific application.
+ ///
+ public int ApplicationId { get; private set; }
+ }
+}
diff --git a/src/Server/Coderr.Server.Api/Core/Environments/Queries/GetEnvironmentsResult.cs b/src/Server/Coderr.Server.Api/Core/Environments/Queries/GetEnvironmentsResult.cs
new file mode 100644
index 00000000..c3727c11
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Environments/Queries/GetEnvironmentsResult.cs
@@ -0,0 +1,13 @@
+namespace Coderr.Server.Api.Core.Environments.Queries
+{
+ ///
+ /// Result for
+ ///
+ public class GetEnvironmentsResult
+ {
+ ///
+ /// Get name of each environment
+ ///
+ public GetEnvironmentsResultItem[] Items { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Environments/Queries/GetEnvironmentsResultItem.cs b/src/Server/Coderr.Server.Api/Core/Environments/Queries/GetEnvironmentsResultItem.cs
new file mode 100644
index 00000000..825fd1d6
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Environments/Queries/GetEnvironmentsResultItem.cs
@@ -0,0 +1,23 @@
+namespace Coderr.Server.Api.Core.Environments.Queries
+{
+ ///
+ /// Item for .
+ ///
+ public class GetEnvironmentsResultItem
+ {
+ ///
+ /// ID
+ ///
+ public int Id { get; set; }
+
+ ///
+ /// Name, like "Production" or "Test"
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// Delete all inbound reports in this environment.
+ ///
+ public bool DeleteIncidents { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Feedback/Commands/SubmitFeedback.cs b/src/Server/Coderr.Server.Api/Core/Feedback/Commands/SubmitFeedback.cs
similarity index 94%
rename from src/Server/OneTrueError.Api/Core/Feedback/Commands/SubmitFeedback.cs
rename to src/Server/Coderr.Server.Api/Core/Feedback/Commands/SubmitFeedback.cs
index 2ab994db..5449e733 100644
--- a/src/Server/OneTrueError.Api/Core/Feedback/Commands/SubmitFeedback.cs
+++ b/src/Server/Coderr.Server.Api/Core/Feedback/Commands/SubmitFeedback.cs
@@ -1,106 +1,106 @@
-using System;
-using System.Collections.Generic;
-using System.ComponentModel.DataAnnotations;
-using DotNetCqs;
-
-namespace OneTrueError.Api.Core.Feedback.Commands
-{
- ///
- /// A user that experienced an error have either followed the link to our website to submit an error or have entered it
- /// directly into our client library integration.
- ///
- public class SubmitFeedback : Command, IValidatableObject
- {
- ///
- /// Initializes a new instance of the class.
- ///
- /// Client side id.
- /// The remote address.
- ///
- /// errorId
- /// or
- /// remoteAddress
- ///
- public SubmitFeedback(string errorId, string remoteAddress)
- {
- if (errorId == null) throw new ArgumentNullException("errorId");
- if (remoteAddress == null) throw new ArgumentNullException("remoteAddress");
- RemoteAddress = remoteAddress;
- ErrorId = errorId;
- CreatedAtUtc = DateTime.UtcNow;
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// Error report identity.
- /// The remote address.
- ///
- /// remoteAddress
- ///
- /// reportId
- public SubmitFeedback(int reportId, string remoteAddress)
- {
- if (remoteAddress == null) throw new ArgumentNullException("remoteAddress");
- if (reportId <= 0) throw new ArgumentOutOfRangeException("reportId");
-
- RemoteAddress = remoteAddress;
- ReportId = reportId;
- CreatedAtUtc = DateTime.UtcNow;
- }
-
- ///
- /// Serialization constructor
- ///
- protected SubmitFeedback()
- {
- }
-
- ///
- /// When the feedback was created in the client library
- ///
- public DateTime CreatedAtUtc { get; set; }
-
- ///
- /// Email address (user want to get status updates)
- ///
- public string Email { get; set; }
-
- ///
- /// Error id generated in our client library. Used to identify error reports before they have been saved into our
- /// system
- ///
- [Required]
- public string ErrorId { get; private set; }
-
- ///
- /// Error description
- ///
- public string Feedback { get; set; }
-
- ///
- /// IP that the user connected from. either taken from the error report or from the HTTP POST if the UI less client
- /// library directed the user to our web site.
- ///
- public string RemoteAddress { get; set; }
-
- ///
- /// PK from the db entry of the error report.
- ///
- public int ReportId { get; private set; }
-
- ///
- /// Validate contents of this command
- ///
- /// validation context
- /// Validation errors if any
- public IEnumerable Validate(ValidationContext validationContext)
- {
- if (validationContext == null) throw new ArgumentNullException("validationContext");
-
- if (string.IsNullOrEmpty(Email) && string.IsNullOrEmpty(Feedback))
- return new[] {new ValidationResult("Email or Feedback must be given")};
- return new ValidationResult[0];
- }
- }
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+
+namespace Coderr.Server.Api.Core.Feedback.Commands
+{
+ ///
+ /// A user that experienced an error have either followed the link to our website to submit an error or have entered it
+ /// directly into our client library integration.
+ ///
+ [Message]
+ public class SubmitFeedback
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Client side id.
+ /// The remote address.
+ ///
+ /// errorId
+ /// or
+ /// remoteAddress
+ ///
+ public SubmitFeedback(string errorId, string remoteAddress)
+ {
+ if (errorId == null) throw new ArgumentNullException("errorId");
+ if (remoteAddress == null) throw new ArgumentNullException("remoteAddress");
+ RemoteAddress = remoteAddress;
+ ErrorId = errorId;
+ CreatedAtUtc = DateTime.UtcNow;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Error report identity.
+ /// The remote address.
+ ///
+ /// remoteAddress
+ ///
+ /// reportId
+ public SubmitFeedback(int reportId, string remoteAddress)
+ {
+ if (remoteAddress == null) throw new ArgumentNullException("remoteAddress");
+ if (reportId <= 0) throw new ArgumentOutOfRangeException("reportId");
+
+ RemoteAddress = remoteAddress;
+ ReportId = reportId;
+ CreatedAtUtc = DateTime.UtcNow;
+ }
+
+ ///
+ /// Serialization constructor
+ ///
+ protected SubmitFeedback()
+ {
+ }
+
+ ///
+ /// When the feedback was created in the client library
+ ///
+ public DateTime CreatedAtUtc { get; set; }
+
+ ///
+ /// Email address (user want to get status updates)
+ ///
+ public string Email { get; set; }
+
+ ///
+ /// Error id generated in our client library. Used to identify error reports before they have been saved into our
+ /// system
+ ///
+ [Required]
+ public string ErrorId { get; private set; }
+
+ ///
+ /// Error description
+ ///
+ public string Feedback { get; set; }
+
+ ///
+ /// IP that the user connected from. either taken from the error report or from the HTTP POST if the UI less client
+ /// library directed the user to our web site.
+ ///
+ public string RemoteAddress { get; set; }
+
+ ///
+ /// PK from the db entry of the error report.
+ ///
+ public int ReportId { get; private set; }
+
+ ///
+ /// Validate contents of this command
+ ///
+ /// validation context
+ /// Validation errors if any
+ public IEnumerable Validate(ValidationContext validationContext)
+ {
+ if (validationContext == null) throw new ArgumentNullException("validationContext");
+
+ if (string.IsNullOrEmpty(Email) && string.IsNullOrEmpty(Feedback))
+ return new[] {new ValidationResult("Email or Feedback must be given")};
+ return new ValidationResult[0];
+ }
+ }
}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Feedback/NamespaceDoc.cs b/src/Server/Coderr.Server.Api/Core/Feedback/NamespaceDoc.cs
new file mode 100644
index 00000000..0bf4ef2d
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Feedback/NamespaceDoc.cs
@@ -0,0 +1,16 @@
+using System.Runtime.CompilerServices;
+
+namespace Coderr.Server.Api.Core.Feedback
+{
+ // This file is Generated by the tool MarkdownToNamespaceDoc. ReadMe.md is the master.
+
+ ///
+ /// Feedback / error description written by the user when the exception was caught.
+ ///
+ ///
+ ///
+ [CompilerGenerated]
+ internal class NamespaceDoc
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Feedback/ReadMe.md b/src/Server/Coderr.Server.Api/Core/Feedback/ReadMe.md
similarity index 100%
rename from src/Server/OneTrueError.Api/Core/Feedback/ReadMe.md
rename to src/Server/Coderr.Server.Api/Core/Feedback/ReadMe.md
diff --git a/src/Server/Coderr.Server.Api/Core/Incidents/Commands/AssignIncident.cs b/src/Server/Coderr.Server.Api/Core/Incidents/Commands/AssignIncident.cs
new file mode 100644
index 00000000..a751f8a9
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Incidents/Commands/AssignIncident.cs
@@ -0,0 +1,48 @@
+using System;
+
+namespace Coderr.Server.Api.Core.Incidents.Commands
+{
+ ///
+ /// Start working on an incident.
+ ///
+ [Command]
+ public class AssignIncident
+ {
+ ///
+ /// Creates new instance of .
+ ///
+ /// Incident being assigned
+ /// Id of the user that got assigned to this incident
+ /// Id of the user that assigned this incident, 0 for system requests
+ public AssignIncident(int incidentId, int assignedTo, int assignedBy)
+ {
+ if (assignedTo <= 0) throw new ArgumentOutOfRangeException(nameof(assignedTo));
+ if (incidentId <= 0) throw new ArgumentOutOfRangeException(nameof(incidentId));
+ if (assignedBy < 0) throw new ArgumentOutOfRangeException(nameof(assignedBy));
+
+ IncidentId = incidentId;
+ AssignedTo = assignedTo;
+ AssignedBy = assignedBy;
+ }
+
+ ///
+ /// Id of the user that assigned this incident.
+ ///
+ public int AssignedBy { get; private set; }
+
+ ///
+ /// Id of the user that got assigned to this incident.
+ ///
+ public int AssignedTo { get; private set; }
+
+ ///
+ /// Incident being assigned.
+ ///
+ public int IncidentId { get; private set; }
+
+ ///
+ /// Optionally specify when the incident was assigned. Default = now.
+ ///
+ public DateTime? AssignedAtUtc { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Incidents/Commands/CloseIncident.cs b/src/Server/Coderr.Server.Api/Core/Incidents/Commands/CloseIncident.cs
similarity index 81%
rename from src/Server/OneTrueError.Api/Core/Incidents/Commands/CloseIncident.cs
rename to src/Server/Coderr.Server.Api/Core/Incidents/Commands/CloseIncident.cs
index b808dbfb..7158d382 100644
--- a/src/Server/OneTrueError.Api/Core/Incidents/Commands/CloseIncident.cs
+++ b/src/Server/Coderr.Server.Api/Core/Incidents/Commands/CloseIncident.cs
@@ -1,68 +1,78 @@
-using System;
-using DotNetCqs;
-
-namespace OneTrueError.Api.Core.Incidents.Commands
-{
- ///
- /// Close incident (i.e. we have corrected the issue)
- ///
- public class CloseIncident : Command
- {
- ///
- /// Creates a new instance of .
- ///
- /// Markdown formatted string detailing how we solved this incident.
- /// Incident that was solved.
- public CloseIncident(string solution, int incidentId)
- {
- if (solution == null) throw new ArgumentNullException("solution");
- if (incidentId <= 0) throw new ArgumentOutOfRangeException("incidentId");
- IncidentId = incidentId;
- Solution = solution;
- }
-
- ///
- /// Serialization constructor.
- ///
- protected CloseIncident()
- {
- }
-
- ///
- /// Can send notifications to everyone which has reported exceptions through our system.
- ///
- public bool CanSendNotification { get; set; }
-
- ///
- ///
- public int IncidentId { get; private set; }
-
- ///
- /// Text to send as email body
- ///
- public string NotificationText { get; set; }
-
- ///
- /// Title of outbound notification.
- ///
- public string NotificationTitle { get; set; }
-
- ///
- /// If this solution can be shared with other OTE customers.
- ///
- public bool ShareSolution { get; set; }
-
- ///
- /// How the incident has been fixed.
- ///
- public string Solution { get; set; }
-
- ///
- /// User that closed the incident
- ///
- ///
- /// Need to be named "UserId" so that the CQS mapper can add the logged in user id
- ///
- public int UserId { get; set; }
- }
+using System;
+
+namespace Coderr.Server.Api.Core.Incidents.Commands
+{
+ ///
+ /// Close incident (i.e. we have corrected the issue)
+ ///
+ [Message]
+ public class CloseIncident
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// Markdown formatted string detailing how we solved this incident.
+ /// Incident that was solved.
+ public CloseIncident(string solution, int incidentId)
+ {
+ if (solution == null) throw new ArgumentNullException("solution");
+ if (incidentId <= 0) throw new ArgumentOutOfRangeException("incidentId");
+ IncidentId = incidentId;
+ Solution = solution;
+ }
+
+ ///
+ /// Serialization constructor.
+ ///
+ protected CloseIncident()
+ {
+ }
+
+ ///
+ /// Which version that incident is solved in (like "1.2.1").
+ ///
+ public string ApplicationVersion { get; set; }
+
+ ///
+ /// Can send notifications to everyone which has reported exceptions through our system.
+ ///
+ public bool CanSendNotification { get; set; }
+
+ ///
+ ///
+ public int IncidentId { get; private set; }
+
+ ///
+ /// Text to send as email body
+ ///
+ public string NotificationText { get; set; }
+
+ ///
+ /// Title of outbound notification.
+ ///
+ public string NotificationTitle { get; set; }
+
+ ///
+ /// If this solution can be shared with other OTE customers.
+ ///
+ public bool ShareSolution { get; set; }
+
+ ///
+ /// How the incident has been fixed.
+ ///
+ public string Solution { get; set; }
+
+ ///
+ /// User that closed the incident
+ ///
+ ///
+ /// Need to be named "UserId" so that the CQS mapper can add the logged in user id
+ ///
+ public int UserId { get; set; }
+
+ ///
+ /// When incident was closed (optional, "now" will be used when not specified)
+ ///
+ public DateTime? ClosedAtUtc { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Incidents/Commands/DeleteIncident.cs b/src/Server/Coderr.Server.Api/Core/Incidents/Commands/DeleteIncident.cs
new file mode 100644
index 00000000..4b88f2a6
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Incidents/Commands/DeleteIncident.cs
@@ -0,0 +1,31 @@
+using System;
+
+namespace Coderr.Server.Api.Core.Incidents.Commands
+{
+ ///
+ /// Delete incidents (old, created in dev environment etc)
+ ///
+ [Message]
+ public class DeleteIncident
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// incident to delete
+ /// should be "yes"
+ public DeleteIncident(int incidentId, string areYouSure)
+ {
+ if (incidentId <= 0) throw new ArgumentOutOfRangeException(nameof(incidentId));
+ if (areYouSure != "yes")
+ throw new ArgumentOutOfRangeException(nameof(areYouSure), areYouSure, "Must be 'yes'.");
+ IncidentId = incidentId;
+ AreYouSure = areYouSure;
+ }
+
+ public int IncidentId { get; private set; }
+ public int? UserId { get; set; }
+
+ public DateTime? DeletedAtUtc { get; set; }
+ public string AreYouSure { get; private set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Incidents/Commands/IgnoreIncident.cs b/src/Server/Coderr.Server.Api/Core/Incidents/Commands/IgnoreIncident.cs
similarity index 86%
rename from src/Server/OneTrueError.Api/Core/Incidents/Commands/IgnoreIncident.cs
rename to src/Server/Coderr.Server.Api/Core/Incidents/Commands/IgnoreIncident.cs
index 77ef4389..9ab4eff3 100644
--- a/src/Server/OneTrueError.Api/Core/Incidents/Commands/IgnoreIncident.cs
+++ b/src/Server/Coderr.Server.Api/Core/Incidents/Commands/IgnoreIncident.cs
@@ -1,40 +1,40 @@
-using System;
-using DotNetCqs;
-
-namespace OneTrueError.Api.Core.Incidents.Commands
-{
- ///
- /// Ignore incident
- ///
- public class IgnoreIncident : Command
- {
- ///
- /// Creates a new instance of .
- ///
- /// incident id
- /// incidentId
- public IgnoreIncident(int incidentId)
- {
- if (incidentId <= 0) throw new ArgumentOutOfRangeException("incidentId");
- IncidentId = incidentId;
- }
-
-
- ///
- /// Serialization constructor
- ///
- protected IgnoreIncident()
- {
- }
-
- ///
- /// Incident to ignore
- ///
- public int IncidentId { get; private set; }
-
- ///
- /// Person that ignored the report.
- ///
- public int UserId { get; set; }
- }
+using System;
+
+namespace Coderr.Server.Api.Core.Incidents.Commands
+{
+ ///
+ /// Ignore incident
+ ///
+ [Message]
+ public class IgnoreIncident
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// incident id
+ /// incidentId
+ public IgnoreIncident(int incidentId)
+ {
+ if (incidentId <= 0) throw new ArgumentOutOfRangeException("incidentId");
+ IncidentId = incidentId;
+ }
+
+
+ ///
+ /// Serialization constructor
+ ///
+ protected IgnoreIncident()
+ {
+ }
+
+ ///
+ /// Incident to ignore
+ ///
+ public int IncidentId { get; private set; }
+
+ ///
+ /// Person that ignored the report.
+ ///
+ public int UserId { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Incidents/Commands/NotifySubscribers.cs b/src/Server/Coderr.Server.Api/Core/Incidents/Commands/NotifySubscribers.cs
new file mode 100644
index 00000000..35413857
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Incidents/Commands/NotifySubscribers.cs
@@ -0,0 +1,37 @@
+using System;
+
+namespace Coderr.Server.Api.Core.Incidents.Commands
+{
+ ///
+ /// Notify all users that have subscribed on an incident.
+ ///
+ [Command]
+ public class NotifySubscribers
+ {
+ public NotifySubscribers(int incidentId)
+ {
+ if (incidentId <= 0) throw new ArgumentOutOfRangeException(nameof(incidentId));
+ IncidentId = incidentId;
+ }
+
+ protected NotifySubscribers()
+ {
+
+ }
+
+ ///
+ /// Incident id
+ ///
+ public int IncidentId { get; private set; }
+ ///
+ /// Text to send as email body
+ ///
+ public string Body { get; set; }
+
+ ///
+ /// Title of outbound notification.
+ ///
+ public string Title { get; set; }
+
+ }
+}
diff --git a/src/Server/Coderr.Server.Api/Core/Incidents/Commands/ReOpenIncident.cs b/src/Server/Coderr.Server.Api/Core/Incidents/Commands/ReOpenIncident.cs
new file mode 100644
index 00000000..5db356b6
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Incidents/Commands/ReOpenIncident.cs
@@ -0,0 +1,40 @@
+using System;
+
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Local
+
+namespace Coderr.Server.Api.Core.Incidents.Commands
+{
+ ///
+ /// An incident which has either been closed or ignored is marked as active again
+ ///
+ [Message]
+ public class ReOpenIncident
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// incident to reopen
+ public ReOpenIncident(int incidentId)
+ {
+ if (incidentId <= 0) throw new ArgumentOutOfRangeException(nameof(incidentId));
+ IncidentId = incidentId;
+ }
+
+ ///
+ /// Serialization constructor
+ ///
+ protected ReOpenIncident()
+ {
+ }
+
+ ///
+ /// Incident to reopen
+ ///
+ public int IncidentId { get; private set; }
+
+ ///
+ /// User requesting item to be reopened.
+ ///
+ public int UserId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Incidents/Events/IncidentAssigned.cs b/src/Server/Coderr.Server.Api/Core/Incidents/Events/IncidentAssigned.cs
new file mode 100644
index 00000000..bc2e19e2
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Incidents/Events/IncidentAssigned.cs
@@ -0,0 +1,55 @@
+using System;
+
+namespace Coderr.Server.Api.Core.Incidents.Events
+{
+ ///
+ /// Someone was assigned to an incident
+ ///
+ [Event]
+ public class IncidentAssigned
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// Incident being assigned
+ /// User assigning the incident
+ /// User that should start working with the incident
+ /// When incident was assigned
+ public IncidentAssigned(int incidentId, int assignedById, int assignedToId, DateTime assignedAtUtc)
+ {
+ if (incidentId <= 0) throw new ArgumentOutOfRangeException(nameof(incidentId));
+ if (assignedById <= 0) throw new ArgumentOutOfRangeException(nameof(assignedById));
+ if (assignedToId <= 0) throw new ArgumentOutOfRangeException(nameof(assignedToId));
+
+ IncidentId = incidentId;
+ AssignedById = assignedById;
+ AssignedToId = assignedToId;
+ AssignedAtUtc = assignedAtUtc;
+ }
+
+ protected IncidentAssigned()
+ {
+
+ }
+
+ ///
+ /// User assigning the incident (delegate work)
+ ///
+ public int AssignedById { get; private set; }
+
+ ///
+ /// User that should start working with the incident
+ ///
+ public int AssignedToId { get; private set; }
+
+ ///
+ /// When the incident was assigned (client side)
+ ///
+ public DateTime AssignedAtUtc { get; private set; }
+
+ ///
+ /// Incident being assigned
+ ///
+ public int IncidentId { get; private set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Incidents/Events/IncidentClosed.cs b/src/Server/Coderr.Server.Api/Core/Incidents/Events/IncidentClosed.cs
new file mode 100644
index 00000000..91c8cfda
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Incidents/Events/IncidentClosed.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Coderr.Server.Api.Core.Incidents.Events
+{
+ [Event]
+ public class IncidentClosed
+ {
+ public IncidentClosed(int applicationId, int incidentId, int userId, string solution, string applicationVersion, DateTime closedAtUtc)
+ {
+ if (incidentId <= 0) throw new ArgumentOutOfRangeException(nameof(incidentId));
+ if (userId <= 0) throw new ArgumentOutOfRangeException(nameof(userId));
+ if (applicationId <= 0) throw new ArgumentOutOfRangeException(nameof(applicationId));
+
+ ApplicationId = applicationId;
+ IncidentId = incidentId;
+ ClosedById = userId;
+ Solution = solution;
+ ApplicationVersion = applicationVersion;
+ ClosedAtUtc = closedAtUtc;
+ }
+
+ protected IncidentClosed()
+ {
+
+ }
+
+ public int ClosedById { get; private set; }
+ public int IncidentId { get;private set; }
+ public string Solution { get;private set; }
+ public string ApplicationVersion { get; private set; }
+ public int ApplicationId { get; set; }
+ public DateTime ClosedAtUtc { get; private set; }
+ }
+}
diff --git a/src/Server/Coderr.Server.Api/Core/Incidents/Events/IncidentDeleted.cs b/src/Server/Coderr.Server.Api/Core/Incidents/Events/IncidentDeleted.cs
new file mode 100644
index 00000000..4cac5799
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Incidents/Events/IncidentDeleted.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Coderr.Server.Api.Core.Incidents.Events
+{
+ [Event]
+ public class IncidentDeleted
+ {
+ public IncidentDeleted(int incidentId, int userId, DateTime deletedAtUtc)
+ {
+ if (incidentId <= 0) throw new ArgumentOutOfRangeException(nameof(incidentId));
+ if (userId <= 0) throw new ArgumentOutOfRangeException(nameof(userId));
+
+ IncidentId = incidentId;
+ DeletedById = userId;
+ DeletedAtUtc = deletedAtUtc;
+ }
+
+ protected IncidentDeleted()
+ {
+
+ }
+
+ public int IncidentId { get;private set; }
+
+ public int DeletedById { get; set; }
+ public DateTime DeletedAtUtc { get; private set; }
+ }
+}
diff --git a/src/Server/OneTrueError.Api/Core/Incidents/Events/IncidentIgnored.cs b/src/Server/Coderr.Server.Api/Core/Incidents/Events/IncidentIgnored.cs
similarity index 76%
rename from src/Server/OneTrueError.Api/Core/Incidents/Events/IncidentIgnored.cs
rename to src/Server/Coderr.Server.Api/Core/Incidents/Events/IncidentIgnored.cs
index ea587cc7..ffe14a2c 100644
--- a/src/Server/OneTrueError.Api/Core/Incidents/Events/IncidentIgnored.cs
+++ b/src/Server/Coderr.Server.Api/Core/Incidents/Events/IncidentIgnored.cs
@@ -1,52 +1,57 @@
-using System;
-using DotNetCqs;
-
-namespace OneTrueError.Api.Core.Incidents.Events
-{
- ///
- /// Our user have configured that all new reports for this incident should be ignored
- ///
- public class IncidentIgnored : ApplicationEvent
- {
- ///
- /// Creates a new instance of .
- ///
- /// incident being ignored
- /// account ignoring the incident
- /// userName for the given account
- ///
- ///
- public IncidentIgnored(int incidentId, int accountId, string userName)
- {
- if (userName == null) throw new ArgumentNullException("userName");
- if (incidentId <= 0) throw new ArgumentOutOfRangeException("incidentId");
- if (accountId <= 0) throw new ArgumentOutOfRangeException("accountId");
-
- IncidentId = incidentId;
- AccountId = accountId;
- UserName = userName;
- }
-
- ///
- /// Serialization constructor
- ///
- protected IncidentIgnored()
- {
- }
-
- ///
- /// User that configured ignore.
- ///
- public int AccountId { get; set; }
-
- ///
- /// Incident id
- ///
- public int IncidentId { get; set; }
-
- ///
- /// Name of the user.
- ///
- public string UserName { get; set; }
- }
+using System;
+
+namespace Coderr.Server.Api.Core.Incidents.Events
+{
+ ///
+ /// Our user have configured that all new reports for this incident should be ignored
+ ///
+ [Message]
+ public class IncidentIgnored
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// Application that the incident belongs to.
+ /// incident being ignored
+ /// account ignoring the incident
+ /// userName for the given account
+ ///
+ ///
+ public IncidentIgnored(int applicationId, int incidentId, int accountId, string userName)
+ {
+ if (userName == null) throw new ArgumentNullException("userName");
+ if (incidentId <= 0) throw new ArgumentOutOfRangeException("incidentId");
+ if (accountId <= 0) throw new ArgumentOutOfRangeException("accountId");
+ if (applicationId <= 0) throw new ArgumentOutOfRangeException(nameof(applicationId));
+
+ ApplicationId = applicationId;
+ IncidentId = incidentId;
+ AccountId = accountId;
+ UserName = userName;
+ }
+
+ ///
+ /// Serialization constructor
+ ///
+ protected IncidentIgnored()
+ {
+ }
+
+ ///
+ /// User that configured ignore.
+ ///
+ public int AccountId { get; set; }
+
+ public int ApplicationId { get; }
+
+ ///
+ /// Incident id
+ ///
+ public int IncidentId { get; set; }
+
+ ///
+ /// Name of the user.
+ ///
+ public string UserName { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Incidents/IncidentOrder.cs b/src/Server/Coderr.Server.Api/Core/Incidents/IncidentOrder.cs
new file mode 100644
index 00000000..5e0eeac7
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Incidents/IncidentOrder.cs
@@ -0,0 +1,28 @@
+namespace Coderr.Server.Api.Core.Incidents
+{
+ ///
+ /// How incidents should be ordered in a list
+ ///
+ public enum IncidentOrder
+ {
+ ///
+ /// Newest incidents first
+ ///
+ Newest,
+
+ ///
+ /// The one that recieved a report most recent.
+ ///
+ LatestReport,
+
+ ///
+ /// The incident with the highest number of reports
+ ///
+ MostReports,
+
+ ///
+ /// The incidents with the most given feedback
+ ///
+ MostFeedback
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Incidents/IncidentSummaryDTO.cs b/src/Server/Coderr.Server.Api/Core/Incidents/IncidentSummaryDTO.cs
new file mode 100644
index 00000000..73e9013f
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Incidents/IncidentSummaryDTO.cs
@@ -0,0 +1,80 @@
+using System;
+
+namespace Coderr.Server.Api.Core.Incidents
+{
+ ///
+ /// A small summary of an incident, typically used to list incidents.
+ ///
+ public class IncidentSummaryDTO
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// incident id
+ /// incident name
+ /// name
+ /// incident id
+ public IncidentSummaryDTO(int id, string name)
+ {
+ if (name == null) throw new ArgumentNullException("name");
+ if (id <= 0) throw new ArgumentOutOfRangeException("id");
+
+ Id = id;
+ Name = name;
+ }
+
+ ///
+ /// Serialization constructor
+ ///
+ protected IncidentSummaryDTO()
+ {
+ }
+
+ ///
+ /// Application that the incident belongs to
+ ///
+ public int ApplicationId { get; set; }
+
+ ///
+ /// Name of that application
+ ///
+ public string ApplicationName { get; set; }
+
+ ///
+ /// When the incident was created (when we received the first report).
+ ///
+ public DateTime CreatedAtUtc { get; set; }
+
+ ///
+ /// Incident id
+ ///
+ public int Id { get; set; }
+
+ ///
+ /// Incident was closed but then received a new error report.
+ ///
+ public bool IsReOpened { get; set; }
+
+ ///
+ /// someone is assigned to this incident
+ ///
+ public int? AssignedToUserId { get; set; }
+
+ ///
+ /// Update is both when the incident was open/closed and when we received a new report. TODO: Should be refactored into
+ /// two fields.
+ ///
+ public DateTime LastUpdateAtUtc { get; set; }
+
+ ///
+ /// Incident name (typically first line of the exception message)
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// Number of reports that we've received. Should be the total amount (including those that have been deleted due to
+ /// retention days).
+ ///
+ public int ReportCount { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Incidents/NamespaceDoc.cs b/src/Server/Coderr.Server.Api/Core/Incidents/NamespaceDoc.cs
new file mode 100644
index 00000000..e4c523d5
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Incidents/NamespaceDoc.cs
@@ -0,0 +1,17 @@
+using System.Runtime.CompilerServices;
+
+namespace Coderr.Server.Api.Core.Incidents
+{
+ // This file is Generated by the tool MarkdownToNamespaceDoc. ReadMe.md is the master.
+
+ ///
+ /// All instances of the same exception are grouped together into an incident (i.e. even if the same exception is
+ /// thrown 100 000 it's still the same incident).
+ ///
+ ///
+ ///
+ [CompilerGenerated]
+ internal class NamespaceDoc
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Incidents/Queries/FindIncidents.cs b/src/Server/Coderr.Server.Api/Core/Incidents/Queries/FindIncidents.cs
new file mode 100644
index 00000000..a43cbdec
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Incidents/Queries/FindIncidents.cs
@@ -0,0 +1,145 @@
+using System;
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Core.Incidents.Queries
+{
+ ///
+ /// Find incidents
+ ///
+ ///
+ ///
+ /// Default query is only open incidents with 20 items per page.
+ ///
+ ///
+ [Message]
+ public class FindIncidents : Query
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ public FindIncidents()
+ {
+ MaxDate = DateTime.MaxValue;
+ ItemsPerPage = 20;
+ }
+
+
+ ///
+ /// Find incidents assigned to the specified user
+ ///
+ public int AssignedToId { get; set; }
+
+ ///
+ /// Empty = find for all applications
+ ///
+ ///
+ /// The application identifier.
+ ///
+ public int[] ApplicationIds { get; set; }
+
+ ///
+ /// Find an incident with a specific collection
+ ///
+ ///
+ ///
+ /// Wildcard search is allowed, i.e. "http*"
+ ///
+ ///
+ public string ContextCollectionName { get; set; }
+
+ ///
+ /// Find an incident with a specific property
+ ///
+ ///
+ ///
+ /// Wildcard search is allowed, i.e. "http*"
+ ///
+ ///
+ public string ContextCollectionPropertyName { get; set; }
+
+ ///
+ /// Find an incident with a specific property value
+ ///
+ ///
+ ///
+ /// Wildcard search is allowed, i.e. "http*"
+ ///
+ ///
+ public string ContextCollectionPropertyValue { get; set; }
+
+ ///
+ /// Which environments we should search in.
+ ///
+ public int[] EnvironmentIds { get; set; }
+
+ ///
+ /// Will be searched in incident.message and report.stacktrace.
+ ///
+ public string FreeText { get; set; }
+
+ ///
+ /// Been assigned to someone
+ ///
+ public bool IsAssigned { get; set; }
+
+ ///
+ /// Include closed incidents
+ ///
+ public bool IsClosed { get; set; }
+
+ ///
+ /// Include ignored incidents
+ ///
+ public bool IsIgnored { get; set; }
+
+ ///
+ /// Incidents that have not been assigned to someone (or closed/ignored).
+ ///
+ public bool IsNew { get; set; }
+
+ ///
+ /// Number of items per page.
+ ///
+ public int ItemsPerPage { get; set; }
+
+ ///
+ /// End of period
+ ///
+ public DateTime MaxDate { get; set; }
+
+ ///
+ /// Start of period
+ ///
+ public DateTime MinDate { get; set; }
+
+ ///
+ /// Page to fetch (one based index)
+ ///
+ public int PageNumber { get; set; }
+
+ ///
+ /// Include reopened incidents
+ ///
+ public bool ReOpened { get; set; }
+
+ ///
+ /// Sort order
+ ///
+ public bool SortAscending { get; set; }
+
+ ///
+ /// Sort type
+ ///
+ public IncidentOrder SortType { get; set; }
+
+ ///
+ /// Incident should have all the specified tags
+ ///
+ public string[] Tags { get; set; }
+
+ ///
+ /// Version (in the form of a version string i.e. "1.2.1")
+ ///
+ public string Version { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Incidents/Queries/FindIncidentsResult.cs b/src/Server/Coderr.Server.Api/Core/Incidents/Queries/FindIncidentsResult.cs
new file mode 100644
index 00000000..fe00deed
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Incidents/Queries/FindIncidentsResult.cs
@@ -0,0 +1,30 @@
+using System.Collections.Generic;
+
+namespace Coderr.Server.Api.Core.Incidents.Queries
+{
+ ///
+ /// Result for .
+ ///
+ public class FindIncidentsResult
+ {
+ ///
+ /// Items
+ ///
+ public IReadOnlyList Items { get; set; }
+
+ ///
+ /// Page number (one based index)
+ ///
+ public int PageNumber { get; set; }
+
+ ///
+ /// Items returned for this page
+ ///
+ public int PageSize { get; set; }
+
+ ///
+ /// Total number of items
+ ///
+ public int TotalCount { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Incidents/Queries/FindIncidentsResultItem.cs b/src/Server/Coderr.Server.Api/Core/Incidents/Queries/FindIncidentsResultItem.cs
new file mode 100644
index 00000000..841a1acb
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Incidents/Queries/FindIncidentsResultItem.cs
@@ -0,0 +1,104 @@
+using System;
+
+namespace Coderr.Server.Api.Core.Incidents.Queries
+{
+ ///
+ /// Item for .
+ ///
+ public class FindIncidentsResultItem
+ {
+ ///
+ /// Creates new instance of .
+ ///
+ /// incident id
+ /// incident name
+ public FindIncidentsResultItem(int id, string name)
+ {
+ if (name == null) throw new ArgumentNullException("name");
+ if (id <= 0) throw new ArgumentOutOfRangeException("id");
+ Id = id;
+ Name = name;
+ }
+
+ ///
+ /// Serialization constructor
+ ///
+ protected FindIncidentsResultItem()
+ {
+ }
+
+ ///
+ /// Id of the application that this incident belongs to
+ ///
+ public int ApplicationId { get; set; }
+
+ ///
+ /// Name of the application that this incident belongs to
+ ///
+ public string ApplicationName { get; set; }
+
+ ///
+ /// When the first report was received.
+ ///
+ public DateTime CreatedAtUtc { get; set; }
+
+ ///
+ /// When the incident was assigned to someone.
+ ///
+ public DateTime? AssignedAtUtc { get; set; }
+
+ ///
+ /// Incident id
+ ///
+ public int Id { get; private set; }
+
+
+ ///
+ /// Incident have been automatically opened again after being closed by a user.
+ ///
+ public bool IsReOpened { get; set; }
+
+ ///
+ /// When we received the last report.
+ ///
+ public DateTime LastReportReceivedAtUtc { get; set; }
+
+ ///
+ /// When someone updated this incident (assigned/closed etc).
+ ///
+ public DateTime LastUpdateAtUtc { get; set; }
+
+ ///
+ /// Incident name
+ ///
+ public string Name { set; get; }
+
+ ///
+ /// Total number of received reports (increased even if the number of stored reports are at the limit)
+ ///
+ public int ReportCount { get; set; }
+
+ ///
+ /// Stores the state temporary to be able to assigned the bool fields
+ ///
+ [IgnoreField]
+ public int IncidentState { get; set; }
+
+ ///
+ /// Ignore future reports for this incident (i.e. no notifications, do not store new reports etc).
+ ///
+ ///
+ ///
+ /// Report counter will still be updated.
+ ///
+ ///
+ public bool IsIgnored => IncidentState == 2;
+
+ ///
+ /// Incident has been marked as solved (i.e. closed)
+ ///
+ public bool IsSolved => IncidentState == 3;
+
+
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Incidents/Queries/GetCollection.cs b/src/Server/Coderr.Server.Api/Core/Incidents/Queries/GetCollection.cs
new file mode 100644
index 00000000..69cd770a
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Incidents/Queries/GetCollection.cs
@@ -0,0 +1,37 @@
+using System;
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Core.Incidents.Queries
+{
+ ///
+ /// Fetch a specific collection from all reports, sorted in descending order.
+ ///
+ public class GetCollection : Query
+ {
+ public GetCollection(int incidentId, string collectionName)
+ {
+ if (incidentId <= 0) throw new ArgumentOutOfRangeException(nameof(incidentId));
+ IncidentId = incidentId;
+ CollectionName = collectionName ?? throw new ArgumentNullException(nameof(collectionName));
+ }
+
+ protected GetCollection()
+ {
+ }
+
+ ///
+ /// Collection name like "ErrorProperties" or "HttpRequest".
+ ///
+ public string CollectionName { get; private set; }
+
+ ///
+ /// Incident that the collection belongs to.
+ ///
+ public int IncidentId { get; private set; }
+
+ ///
+ /// Collection limit.
+ ///
+ public int MaxNumberOfCollections { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Incidents/Queries/GetCollectionResult.cs b/src/Server/Coderr.Server.Api/Core/Incidents/Queries/GetCollectionResult.cs
new file mode 100644
index 00000000..01ecb34b
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Incidents/Queries/GetCollectionResult.cs
@@ -0,0 +1,13 @@
+namespace Coderr.Server.Api.Core.Incidents.Queries
+{
+ ///
+ /// Result for .
+ ///
+ public class GetCollectionResult
+ {
+ ///
+ /// Fetched collections.
+ ///
+ public GetCollectionResultItem[] Items { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Incidents/Queries/GetCollectionResultItem.cs b/src/Server/Coderr.Server.Api/Core/Incidents/Queries/GetCollectionResultItem.cs
new file mode 100644
index 00000000..6952e2f5
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Incidents/Queries/GetCollectionResultItem.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+
+namespace Coderr.Server.Api.Core.Incidents.Queries
+{
+ ///
+ /// A collection
+ ///
+ public class GetCollectionResultItem
+ {
+ ///
+ /// Properties in the collection (for instance "Url" if this is the HTTP request).
+ ///
+ public Dictionary Properties { get; set; }
+
+ ///
+ /// Date for the report that this collection is for.
+ ///
+ public DateTime ReportDate { get; set; }
+
+ ///
+ /// Id of the report that this collection was received in.
+ ///
+ public int ReportId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Incidents/Queries/GetIncident.cs b/src/Server/Coderr.Server.Api/Core/Incidents/Queries/GetIncident.cs
similarity index 91%
rename from src/Server/OneTrueError.Api/Core/Incidents/Queries/GetIncident.cs
rename to src/Server/Coderr.Server.Api/Core/Incidents/Queries/GetIncident.cs
index 781059ae..0c18d101 100644
--- a/src/Server/OneTrueError.Api/Core/Incidents/Queries/GetIncident.cs
+++ b/src/Server/Coderr.Server.Api/Core/Incidents/Queries/GetIncident.cs
@@ -1,35 +1,36 @@
-using System;
-using DotNetCqs;
-
-namespace OneTrueError.Api.Core.Incidents.Queries
-{
- ///
- /// Get incident query
- ///
- public class GetIncident : Query
- {
- ///
- /// Creates a new instance of .
- ///
- /// incident id
- /// incidentId
- public GetIncident(int incidentId)
- {
- if (incidentId <= 0) throw new ArgumentOutOfRangeException("incidentId");
- IncidentId = incidentId;
- }
-
-
- ///
- /// Serialization constructor.
- ///
- protected GetIncident()
- {
- }
-
- ///
- /// Incident id
- ///
- public int IncidentId { get; private set; }
- }
+using System;
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Core.Incidents.Queries
+{
+ ///
+ /// Get incident query
+ ///
+ [Message]
+ public class GetIncident : Query
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// incident id
+ /// incidentId
+ public GetIncident(int incidentId)
+ {
+ if (incidentId <= 0) throw new ArgumentOutOfRangeException("incidentId");
+ IncidentId = incidentId;
+ }
+
+
+ ///
+ /// Serialization constructor.
+ ///
+ protected GetIncident()
+ {
+ }
+
+ ///
+ /// Incident id
+ ///
+ public int IncidentId { get; private set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Incidents/Queries/GetIncidentForClosePage.cs b/src/Server/Coderr.Server.Api/Core/Incidents/Queries/GetIncidentForClosePage.cs
new file mode 100644
index 00000000..f11d52f6
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Incidents/Queries/GetIncidentForClosePage.cs
@@ -0,0 +1,35 @@
+using System;
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Core.Incidents.Queries
+{
+ ///
+ /// Get incident information tailored for the close page.
+ ///
+ [Message]
+ public class GetIncidentForClosePage : Query
+ {
+ ///
+ /// Serialization constructor
+ ///
+ protected GetIncidentForClosePage()
+ {
+ }
+
+ ///
+ /// Creates a new instance of .
+ ///
+ /// incident id
+ /// incidentId
+ public GetIncidentForClosePage(int incidentId)
+ {
+ if (incidentId <= 0) throw new ArgumentOutOfRangeException("incidentId");
+ IncidentId = incidentId;
+ }
+
+ ///
+ /// Incident id
+ ///
+ public int IncidentId { get; private set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Incidents/Queries/GetIncidentForClosePageResult.cs b/src/Server/Coderr.Server.Api/Core/Incidents/Queries/GetIncidentForClosePageResult.cs
similarity index 87%
rename from src/Server/OneTrueError.Api/Core/Incidents/Queries/GetIncidentForClosePageResult.cs
rename to src/Server/Coderr.Server.Api/Core/Incidents/Queries/GetIncidentForClosePageResult.cs
index 188d7441..6d8e4903 100644
--- a/src/Server/OneTrueError.Api/Core/Incidents/Queries/GetIncidentForClosePageResult.cs
+++ b/src/Server/Coderr.Server.Api/Core/Incidents/Queries/GetIncidentForClosePageResult.cs
@@ -1,18 +1,18 @@
-namespace OneTrueError.Api.Core.Incidents.Queries
-{
- ///
- /// Result for .
- ///
- public class GetIncidentForClosePageResult
- {
- ///
- /// A summary of the incident
- ///
- public string Description { get; set; }
-
- ///
- /// Number of update subscribers (i.e. users that want status updates).
- ///
- public int SubscriberCount { get; set; }
- }
+namespace Coderr.Server.Api.Core.Incidents.Queries
+{
+ ///
+ /// Result for .
+ ///
+ public class GetIncidentForClosePageResult
+ {
+ ///
+ /// A summary of the incident
+ ///
+ public string Description { get; set; }
+
+ ///
+ /// Number of update subscribers (i.e. users that want status updates).
+ ///
+ public int SubscriberCount { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Incidents/Queries/GetIncidentResult.cs b/src/Server/Coderr.Server.Api/Core/Incidents/Queries/GetIncidentResult.cs
new file mode 100644
index 00000000..2706993d
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Incidents/Queries/GetIncidentResult.cs
@@ -0,0 +1,171 @@
+using System;
+
+namespace Coderr.Server.Api.Core.Incidents.Queries
+{
+ ///
+ /// Keeps track of all occurrences of a single incident (i.e. error reports which generates the same hash code)
+ ///
+ public class GetIncidentResult
+ {
+ private string _description;
+
+
+ ///
+ /// Application that the incident belongs to
+ ///
+ public int ApplicationId { get; private set; }
+
+ ///
+ /// When it was assigned to the person.
+ ///
+ public DateTime? AssignedAtUtc { get; set; }
+
+ ///
+ /// User name of the person that this incident is assigned to.
+ ///
+ public string AssignedTo { get; set; }
+
+ ///
+ /// User assigned to the incident.
+ ///
+ public int? AssignedToId { get; set; }
+
+ ///
+ /// Context collection names.
+ ///
+ public string[] ContextCollections { get; set; }
+
+ ///
+ /// When the incident was created (when we received the first exception).
+ ///
+ public DateTime CreatedAtUtc { get; private set; }
+
+ ///
+ /// Daily statistics.
+ ///
+ public ReportDay[] DayStatistics { get; set; }
+
+ ///
+ /// Error description (exception message)
+ ///
+ public string Description
+ {
+ get
+ {
+ if (string.IsNullOrEmpty(_description))
+ return "Ooops Error!";
+
+ return _description;
+ }
+ set => _description = value;
+ }
+
+ ///
+ /// facts
+ ///
+ public QuickFact[] Facts { get; set; }
+
+ ///
+ /// Full name of the exception message.
+ ///
+ public string FullName { get; private set; }
+
+ ///
+ /// Used to identify this incident when the hash code is the same as for other incidents.
+ ///
+ ///
+ public string HashCodeIdentifier { get; private set; }
+
+ ///
+ /// primary key
+ ///
+ public int Id { get; private set; }
+
+ ///
+ /// Stores the state temporary to be able to assigned the bool fields
+ ///
+ [IgnoreField]
+ public int IncidentState { get; set; }
+
+ ///
+ /// Ignore future reports for this incident (i.e. no notifications, do not store new reports etc).
+ ///
+ ///
+ ///
+ /// Report counter will still be updated.
+ ///
+ ///
+ public bool IsIgnored => IncidentState == 2;
+
+ ///
+ /// If the incident was closed and then received error reports again.
+ ///
+ public bool IsReOpened { get; set; }
+
+ ///
+ /// Share solution with the Coderr community.
+ ///
+ public bool IsSolutionShared { get; set; }
+
+ ///
+ /// Incident has been marked as solved (i.e. closed)
+ ///
+ public bool IsSolved => IncidentState == 3;
+
+ ///
+ /// When we received the last report for this incident.
+ ///
+ public DateTime LastReportReceivedAtUtc { get; set; }
+
+ ///
+ /// Solution written last time (if is true).
+ ///
+ public DateTime PreviousSolutionAtUtc { get; set; }
+
+ ///
+ /// Date if is true.
+ ///
+ public DateTime ReOpenedAtUtc { get; set; }
+
+
+ ///
+ /// Number of reports received to date.
+ ///
+ public int ReportCount { get; set; }
+
+ ///
+ /// Generated hash code
+ ///
+ public string ReportHashCode { get; private set; }
+
+ ///
+ /// How the incident was solved (the last time)
+ ///
+ public string Solution { get; set; }
+
+ ///
+ /// When the incident was closed/solved.
+ ///
+ public DateTime SolvedAtUtc { get; set; }
+
+ ///
+ /// Stack trace.
+ ///
+ public string StackTrace { get; set; }
+
+ ///
+ /// Identified StackOverflow tags.
+ ///
+ public string[] Tags { get; set; }
+
+ ///
+ /// When the incident was updated (either a new report or changes to the actual incident)
+ ///
+ public DateTime UpdatedAtUtc { get; private set; }
+
+ public SuggestedIncidentSolution[] SuggestedSolutions { get; set; }
+ public HighlightedContextData[] HighlightedContextData { get; set; }
+
+ public RelatedIncident[] RelatedIncidents { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Incidents/Queries/GetIncidentStatistics.cs b/src/Server/Coderr.Server.Api/Core/Incidents/Queries/GetIncidentStatistics.cs
similarity index 75%
rename from src/Server/OneTrueError.Api/Core/Incidents/Queries/GetIncidentStatistics.cs
rename to src/Server/Coderr.Server.Api/Core/Incidents/Queries/GetIncidentStatistics.cs
index 057266e1..72a65489 100644
--- a/src/Server/OneTrueError.Api/Core/Incidents/Queries/GetIncidentStatistics.cs
+++ b/src/Server/Coderr.Server.Api/Core/Incidents/Queries/GetIncidentStatistics.cs
@@ -1,23 +1,24 @@
-using DotNetCqs;
-
-namespace OneTrueError.Api.Core.Incidents.Queries
-{
- ///
- /// Get statistics (i.e. history for a certain period of time)
- ///
- public class GetIncidentStatistics : Query
- {
- ///
- /// Incident to get stats for.
- ///
- public int IncidentId { get; set; }
-
- ///
- /// Amount of time to look back (i.e. startdate = DateTime.Now.Substract(WindowSize))
- ///
- ///
- /// 1 = switch to hours
- ///
- public int NumberOfDays { get; set; }
- }
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Core.Incidents.Queries
+{
+ ///
+ /// Get statistics (i.e. history for a certain period of time)
+ ///
+ [Message]
+ public class GetIncidentStatistics : Query
+ {
+ ///
+ /// Incident to get stats for.
+ ///
+ public int IncidentId { get; set; }
+
+ ///
+ /// Amount of time to look back (i.e. start date = DateTime.Now.Substract(WindowSize))
+ ///
+ ///
+ /// 1 = switch to hours
+ ///
+ public int NumberOfDays { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Incidents/Queries/GetIncidentStatisticsResult.cs b/src/Server/Coderr.Server.Api/Core/Incidents/Queries/GetIncidentStatisticsResult.cs
similarity index 85%
rename from src/Server/OneTrueError.Api/Core/Incidents/Queries/GetIncidentStatisticsResult.cs
rename to src/Server/Coderr.Server.Api/Core/Incidents/Queries/GetIncidentStatisticsResult.cs
index f5b35107..179bed5c 100644
--- a/src/Server/OneTrueError.Api/Core/Incidents/Queries/GetIncidentStatisticsResult.cs
+++ b/src/Server/Coderr.Server.Api/Core/Incidents/Queries/GetIncidentStatisticsResult.cs
@@ -1,19 +1,19 @@
-namespace OneTrueError.Api.Core.Incidents.Queries
-{
- ///
- /// Result for .
- ///
- public class GetIncidentStatisticsResult
- {
- ///
- /// Labels (dates)
- ///
- public string[] Labels { get; set; }
-
-
- ///
- /// Incident counts per date
- ///
- public int[] Values { get; set; }
- }
+namespace Coderr.Server.Api.Core.Incidents.Queries
+{
+ ///
+ /// Result for .
+ ///
+ public class GetIncidentStatisticsResult
+ {
+ ///
+ /// Labels (dates)
+ ///
+ public string[] Labels { get; set; }
+
+
+ ///
+ /// Incident counts per date
+ ///
+ public int[] Values { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Incidents/Queries/HighlightedContextData.cs b/src/Server/Coderr.Server.Api/Core/Incidents/Queries/HighlightedContextData.cs
new file mode 100644
index 00000000..e5ce4864
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Incidents/Queries/HighlightedContextData.cs
@@ -0,0 +1,36 @@
+namespace Coderr.Server.Api.Core.Incidents.Queries
+{
+ ///
+ /// Context data that can help the developer to directly understand why the exception happened.
+ ///
+ ///
+ ///
+ /// For instance for Page Not Found this is the URL and the Referrer.
+ ///
+ ///
+ public class HighlightedContextData
+ {
+ ///
+ /// Why this data helps and what it means.
+ ///
+ public string Description { get; set; }
+
+ ///
+ /// Name ("UrlReferrer", "Url", "HttpCode" etc).
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// Optional url that the user can click on to get more information
+ ///
+ public string Url { get; set; }
+
+ ///
+ /// Value to show (one per report or only from the latest report).
+ ///
+ ///
+ /// Values should be sorted i priority order (first item will be displayed directly)
+ ///
+ public string[] Value { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Incidents/Queries/QuickFact.cs b/src/Server/Coderr.Server.Api/Core/Incidents/Queries/QuickFact.cs
new file mode 100644
index 00000000..ebb23590
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Incidents/Queries/QuickFact.cs
@@ -0,0 +1,36 @@
+namespace Coderr.Server.Api.Core.Incidents.Queries
+{
+ ///
+ /// Quick fact for incidents.
+ ///
+ ///
+ ///
+ /// For instance number of reports, when the incident was created, number of affected users etc.
+ ///
+ ///
+ public class QuickFact
+ {
+ ///
+ /// what this fact displays
+ ///
+ public string Description { get; set; }
+
+ ///
+ /// Fact title (heading)
+ ///
+ public string Title { get; set; }
+
+ ///
+ /// Optional url to get more information.
+ ///
+ public string Url { get; set; }
+
+ ///
+ /// Value to show
+ ///
+ ///
+ /// For multiple values; separate them with semi colons.
+ ///
+ public string Value { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Incidents/Queries/RelatedIncident.cs b/src/Server/Coderr.Server.Api/Core/Incidents/Queries/RelatedIncident.cs
new file mode 100644
index 00000000..fa5edd50
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Incidents/Queries/RelatedIncident.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace Coderr.Server.Api.Core.Incidents.Queries
+{
+ public class RelatedIncident
+ {
+ public int ApplicationId { get; set; }
+ public string ApplicationName { get; set; }
+ public DateTime CreatedAtUtc { get; set; }
+ public int IncidentId { get; set; }
+ public string Title { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Incidents/Queries/ReportDay.cs b/src/Server/Coderr.Server.Api/Core/Incidents/Queries/ReportDay.cs
similarity index 84%
rename from src/Server/OneTrueError.Api/Core/Incidents/Queries/ReportDay.cs
rename to src/Server/Coderr.Server.Api/Core/Incidents/Queries/ReportDay.cs
index f8267420..1a4b2f8c 100644
--- a/src/Server/OneTrueError.Api/Core/Incidents/Queries/ReportDay.cs
+++ b/src/Server/Coderr.Server.Api/Core/Incidents/Queries/ReportDay.cs
@@ -1,20 +1,20 @@
-using System;
-
-namespace OneTrueError.Api.Core.Incidents.Queries
-{
- ///
- /// A day in our statistics
- ///
- public class ReportDay
- {
- ///
- /// Number of items this day
- ///
- public int Count { get; set; }
-
- ///
- /// Date
- ///
- public DateTime Date { get; set; }
- }
+using System;
+
+namespace Coderr.Server.Api.Core.Incidents.Queries
+{
+ ///
+ /// A day in our statistics
+ ///
+ public class ReportDay
+ {
+ ///
+ /// Number of items this day
+ ///
+ public int Count { get; set; }
+
+ ///
+ /// Date
+ ///
+ public DateTime Date { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Incidents/Queries/SuggestedIncidentSolution.cs b/src/Server/Coderr.Server.Api/Core/Incidents/Queries/SuggestedIncidentSolution.cs
new file mode 100644
index 00000000..6bc4be19
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Incidents/Queries/SuggestedIncidentSolution.cs
@@ -0,0 +1,19 @@
+namespace Coderr.Server.Api.Core.Incidents.Queries
+{
+ ///
+ /// A suggested solution for the incident
+ ///
+ public class SuggestedIncidentSolution
+ {
+ ///
+ /// Common reasons to why this exception is thrown.
+ ///
+ public string Reason { get; set; }
+
+
+ ///
+ /// How the incident can be solved.
+ ///
+ public string SuggestedSolution { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Incidents/ReadMe.md b/src/Server/Coderr.Server.Api/Core/Incidents/ReadMe.md
similarity index 100%
rename from src/Server/OneTrueError.Api/Core/Incidents/ReadMe.md
rename to src/Server/Coderr.Server.Api/Core/Incidents/ReadMe.md
diff --git a/src/Server/Coderr.Server.Api/Core/Invitations/Commands/DeleteInvitation.cs b/src/Server/Coderr.Server.Api/Core/Invitations/Commands/DeleteInvitation.cs
new file mode 100644
index 00000000..3a81a5a2
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Invitations/Commands/DeleteInvitation.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Coderr.Server.Api.Core.Invitations.Commands
+{
+ [Message]
+ public class DeleteInvitation
+ {
+ public int ApplicationId { get; set; }
+ public string InvitedEmailAddress { get; set; }
+
+ }
+}
diff --git a/src/Server/OneTrueError.Api/Core/Invitations/Commands/InviteUser.cs b/src/Server/Coderr.Server.Api/Core/Invitations/Commands/InviteUser.cs
similarity index 91%
rename from src/Server/OneTrueError.Api/Core/Invitations/Commands/InviteUser.cs
rename to src/Server/Coderr.Server.Api/Core/Invitations/Commands/InviteUser.cs
index adec93de..ec8e4ba4 100644
--- a/src/Server/OneTrueError.Api/Core/Invitations/Commands/InviteUser.cs
+++ b/src/Server/Coderr.Server.Api/Core/Invitations/Commands/InviteUser.cs
@@ -1,58 +1,58 @@
-using System;
-using DotNetCqs;
-
-namespace OneTrueError.Api.Core.Invitations.Commands
-{
- ///
- /// Invite a user to participate in an application.
- ///
- ///
- ///
- /// Will send an invitation email to the user if the email is not for a registered user, otherwise we'll just
- /// add the user as a member of the specified application.
- ///
- ///
- public class InviteUser : Command
- {
- ///
- /// Create a new instance of .
- ///
- /// Application to gain access to
- /// Email for the given user.
- public InviteUser(int applicationId, string emailAddress)
- {
- if (emailAddress == null) throw new ArgumentNullException("emailAddress");
- if (applicationId <= 0) throw new ArgumentOutOfRangeException("applicationId");
- ApplicationId = applicationId;
- EmailAddress = emailAddress;
- }
-
- ///
- /// Serialization constructor
- ///
- protected InviteUser()
- {
- }
-
- ///
- /// Application that the user will get access to.
- ///
- public int ApplicationId { get; set; }
-
- ///
- /// Email to invited user.
- ///
- public string EmailAddress { get; private set; }
-
- ///
- /// A text written by the user to describe why the invite was sent.
- ///
- public string Text { get; set; }
-
- ///
- /// User that invited
- ///
- [IgnoreField]
- public int UserId { get; set; }
- }
+using System;
+
+namespace Coderr.Server.Api.Core.Invitations.Commands
+{
+ ///
+ /// Invite a user to participate in an application.
+ ///
+ ///
+ ///
+ /// Will send an invitation email to the user if the email is not for a registered user, otherwise we'll just
+ /// add the user as a member of the specified application.
+ ///
+ ///
+ [Message]
+ public class InviteUser
+ {
+ ///
+ /// Create a new instance of .
+ ///
+ /// Application to gain access to
+ /// Email for the given user.
+ public InviteUser(int applicationId, string emailAddress)
+ {
+ if (emailAddress == null) throw new ArgumentNullException("emailAddress");
+ if (applicationId <= 0) throw new ArgumentOutOfRangeException("applicationId");
+ ApplicationId = applicationId;
+ EmailAddress = emailAddress;
+ }
+
+ ///
+ /// Serialization constructor
+ ///
+ protected InviteUser()
+ {
+ }
+
+ ///
+ /// Application that the user will get access to.
+ ///
+ public int ApplicationId { get; set; }
+
+ ///
+ /// Email to invited user.
+ ///
+ public string EmailAddress { get; private set; }
+
+ ///
+ /// A text written by the user to describe why the invite was sent.
+ ///
+ public string Text { get; set; }
+
+ ///
+ /// User that invited
+ ///
+ [IgnoreField]
+ public int UserId { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Invitations/Events/InvitationDeleted.cs b/src/Server/Coderr.Server.Api/Core/Invitations/Events/InvitationDeleted.cs
new file mode 100644
index 00000000..bc1e2249
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Invitations/Events/InvitationDeleted.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Coderr.Server.Api.Core.Invitations.Events
+{
+ [Event]
+ public class InvitationDeleted
+ {
+ public int InvitationId { get; set; }
+ public string InvitedEmailAddress { get; set; }
+ public int[] ApplicationIds { get; set; }
+ }
+}
diff --git a/src/Server/Coderr.Server.Api/Core/Invitations/NamespaceDoc.cs b/src/Server/Coderr.Server.Api/Core/Invitations/NamespaceDoc.cs
new file mode 100644
index 00000000..0c53d9b7
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Invitations/NamespaceDoc.cs
@@ -0,0 +1,16 @@
+using System.Runtime.CompilerServices;
+
+namespace Coderr.Server.Api.Core.Invitations
+{
+ // This file is Generated by the tool MarkdownToNamespaceDoc. ReadMe.md is the master.
+
+ ///
+ /// Invitations are sent on application basis.
+ ///
+ ///
+ ///
+ [CompilerGenerated]
+ internal class NamespaceDoc
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Invitations/Queries/GetInvitationByKey.cs b/src/Server/Coderr.Server.Api/Core/Invitations/Queries/GetInvitationByKey.cs
similarity index 91%
rename from src/Server/OneTrueError.Api/Core/Invitations/Queries/GetInvitationByKey.cs
rename to src/Server/Coderr.Server.Api/Core/Invitations/Queries/GetInvitationByKey.cs
index 03727044..69faafc2 100644
--- a/src/Server/OneTrueError.Api/Core/Invitations/Queries/GetInvitationByKey.cs
+++ b/src/Server/Coderr.Server.Api/Core/Invitations/Queries/GetInvitationByKey.cs
@@ -1,34 +1,35 @@
-using System;
-using DotNetCqs;
-
-namespace OneTrueError.Api.Core.Invitations.Queries
-{
- ///
- /// Get invitation by using the emailed invitation key
- ///
- public class GetInvitationByKey : Query
- {
- ///
- /// Creates a new instance of .
- ///
- /// Emailed key
- /// invitationKey
- public GetInvitationByKey(string invitationKey)
- {
- if (invitationKey == null) throw new ArgumentNullException("invitationKey");
- InvitationKey = invitationKey;
- }
-
- ///
- /// Serialization constructor
- ///
- protected GetInvitationByKey()
- {
- }
-
- ///
- /// Invitation key
- ///
- public string InvitationKey { get; private set; }
- }
+using System;
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Core.Invitations.Queries
+{
+ ///
+ /// Get invitation by using the emailed invitation key
+ ///
+ [Message]
+ public class GetInvitationByKey : Query
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// Emailed key
+ /// invitationKey
+ public GetInvitationByKey(string invitationKey)
+ {
+ if (invitationKey == null) throw new ArgumentNullException("invitationKey");
+ InvitationKey = invitationKey;
+ }
+
+ ///
+ /// Serialization constructor
+ ///
+ protected GetInvitationByKey()
+ {
+ }
+
+ ///
+ /// Invitation key
+ ///
+ public string InvitationKey { get; private set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Invitations/Queries/GetInvitationByKeyResult.cs b/src/Server/Coderr.Server.Api/Core/Invitations/Queries/GetInvitationByKeyResult.cs
similarity index 82%
rename from src/Server/OneTrueError.Api/Core/Invitations/Queries/GetInvitationByKeyResult.cs
rename to src/Server/Coderr.Server.Api/Core/Invitations/Queries/GetInvitationByKeyResult.cs
index 32839128..5f2cd19a 100644
--- a/src/Server/OneTrueError.Api/Core/Invitations/Queries/GetInvitationByKeyResult.cs
+++ b/src/Server/Coderr.Server.Api/Core/Invitations/Queries/GetInvitationByKeyResult.cs
@@ -1,13 +1,13 @@
-namespace OneTrueError.Api.Core.Invitations.Queries
-{
- ///
- /// Result for .
- ///
- public class GetInvitationByKeyResult
- {
- ///
- /// Email address specified when sending the invitation.
- ///
- public string EmailAddress { get; set; }
- }
+namespace Coderr.Server.Api.Core.Invitations.Queries
+{
+ ///
+ /// Result for .
+ ///
+ public class GetInvitationByKeyResult
+ {
+ ///
+ /// Email address specified when sending the invitation.
+ ///
+ public string EmailAddress { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Invitations/ReadMe.md b/src/Server/Coderr.Server.Api/Core/Invitations/ReadMe.md
similarity index 100%
rename from src/Server/OneTrueError.Api/Core/Invitations/ReadMe.md
rename to src/Server/Coderr.Server.Api/Core/Invitations/ReadMe.md
diff --git a/src/Server/Coderr.Server.Api/Core/Messaging/Commands/NamespaceDoc.cs b/src/Server/Coderr.Server.Api/Core/Messaging/Commands/NamespaceDoc.cs
new file mode 100644
index 00000000..b667f532
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Messaging/Commands/NamespaceDoc.cs
@@ -0,0 +1,18 @@
+using System.Runtime.CompilerServices;
+
+namespace Coderr.Server.Api.Core.Messaging.Commands
+{
+ // This file is Generated by the tool MarkdownToNamespaceDoc. ReadMe.md is the master.
+
+ ///
+ /// User related information (such as name, notifcation settings etc.)
+ ///
+ ///
+ /// While accounts are for login authentication and authorization, users are for information about the individual.
+ ///
+ ///
+ [CompilerGenerated]
+ class NamespaceDoc
+ {
+ }
+}
diff --git a/src/Server/OneTrueError.Api/Core/Messaging/Commands/ReadMe.md b/src/Server/Coderr.Server.Api/Core/Messaging/Commands/ReadMe.md
similarity index 100%
rename from src/Server/OneTrueError.Api/Core/Messaging/Commands/ReadMe.md
rename to src/Server/Coderr.Server.Api/Core/Messaging/Commands/ReadMe.md
diff --git a/src/Server/Coderr.Server.Api/Core/Messaging/Commands/SendEmail.cs b/src/Server/Coderr.Server.Api/Core/Messaging/Commands/SendEmail.cs
new file mode 100644
index 00000000..bace4f6f
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Messaging/Commands/SendEmail.cs
@@ -0,0 +1,33 @@
+using System;
+
+namespace Coderr.Server.Api.Core.Messaging.Commands
+{
+ ///
+ /// Send an email.
+ ///
+ [Message]
+ public class SendEmail
+ {
+ ///
+ /// Create a new instance of .
+ ///
+ /// Message to send
+ public SendEmail(EmailMessage message)
+ {
+ if (message == null) throw new ArgumentNullException(nameof(message));
+ EmailMessage = message;
+ }
+
+ ///
+ /// Serialization constructor
+ ///
+ protected SendEmail()
+ {
+ }
+
+ ///
+ /// Message to send
+ ///
+ public EmailMessage EmailMessage { get; private set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Messaging/Commands/SendSms.cs b/src/Server/Coderr.Server.Api/Core/Messaging/Commands/SendSms.cs
similarity index 84%
rename from src/Server/OneTrueError.Api/Core/Messaging/Commands/SendSms.cs
rename to src/Server/Coderr.Server.Api/Core/Messaging/Commands/SendSms.cs
index ced29ace..a6831349 100644
--- a/src/Server/OneTrueError.Api/Core/Messaging/Commands/SendSms.cs
+++ b/src/Server/Coderr.Server.Api/Core/Messaging/Commands/SendSms.cs
@@ -1,50 +1,50 @@
-using System;
-using DotNetCqs;
-
-namespace OneTrueError.Api.Core.Messaging.Commands
-{
- ///
- /// Send a cell phone text.
- ///
- ///
- ///
- /// Requires a prepaid account at http://onetrueerror.com/services/sms. Add your SMS Api key and the shared
- /// secret in your web.config.
- ///
- ///
- ///
- ///
- /// ]]>
- ///
- ///
- public class SendSms : Command
- {
- ///
- /// Creates a new instance of .
- ///
- ///
- /// E.164 formatted number (]]>, example: +467012345
- ///
- /// Message. 160 chars is max for one SMS.
- /// phoneNumber; message
- public SendSms(string phoneNumber, string message)
- {
- if (phoneNumber == null) throw new ArgumentNullException("phoneNumber");
- if (message == null) throw new ArgumentNullException("message");
-
- PhoneNumber = phoneNumber;
- Message = message;
- }
-
- ///
- /// Message. 160 chars is max for one SMS.
- ///
- public string Message { get; set; }
-
- ///
- /// E.164 formatted number (]]>, example: +467012345
- ///
- public string PhoneNumber { get; set; }
- }
+using System;
+
+namespace Coderr.Server.Api.Core.Messaging.Commands
+{
+ ///
+ /// Send a cell phone text.
+ ///
+ ///
+ ///
+ /// Requires a prepaid account at http://coderr.io/services/sms. Add your SMS Api key and the shared
+ /// secret in your web.config.
+ ///
+ ///
+ ///
+ ///
+ /// ]]>
+ ///
+ ///
+ [Message]
+ public class SendSms
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ ///
+ /// E.164 formatted number (]]>, example: +467012345
+ ///
+ /// Message. 160 chars is max for one SMS.
+ /// phoneNumber; message
+ public SendSms(string phoneNumber, string message)
+ {
+ if (phoneNumber == null) throw new ArgumentNullException("phoneNumber");
+ if (message == null) throw new ArgumentNullException("message");
+
+ PhoneNumber = phoneNumber;
+ Message = message;
+ }
+
+ ///
+ /// Message. 160 chars is max for one SMS.
+ ///
+ public string Message { get; set; }
+
+ ///
+ /// E.164 formatted number (]]>, example: +467012345
+ ///
+ public string PhoneNumber { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Messaging/Commands/SendTemplateEmail.cs b/src/Server/Coderr.Server.Api/Core/Messaging/Commands/SendTemplateEmail.cs
similarity index 91%
rename from src/Server/OneTrueError.Api/Core/Messaging/Commands/SendTemplateEmail.cs
rename to src/Server/Coderr.Server.Api/Core/Messaging/Commands/SendTemplateEmail.cs
index e7fe0788..59f26275 100644
--- a/src/Server/OneTrueError.Api/Core/Messaging/Commands/SendTemplateEmail.cs
+++ b/src/Server/Coderr.Server.Api/Core/Messaging/Commands/SendTemplateEmail.cs
@@ -1,66 +1,66 @@
-using System;
-using DotNetCqs;
-
-namespace OneTrueError.Api.Core.Messaging.Commands
-{
- ///
- /// Send email using a template.
- ///
- public class SendTemplateEmail : Command
- {
- ///
- /// Creates a new instance of .
- ///
- /// Mail title (i.e. not the subject)
- ///
- /// Template to load (should be a sub folder to the invoking class, look at
- /// RequestPasswordResetHandler for an example.
- ///
- ///
- public SendTemplateEmail(string mailTitle, string templateName)
- {
- if (mailTitle == null) throw new ArgumentNullException("mailTitle");
- if (templateName == null) throw new ArgumentNullException("templateName");
-
- MailTitle = mailTitle;
- TemplateName = templateName;
- }
-
- ///
- /// Serialization constructor
- ///
- protected SendTemplateEmail()
- {
- }
-
- ///
- /// Mail title (in the layout template)
- ///
- public string MailTitle { get; set; }
-
- ///
- /// View model
- ///
- public object Model { get; set; }
-
- ///
- /// Resources to use in the template
- ///
- public EmailResource[] Resources { get; set; }
-
- ///
- /// Mail subject.
- ///
- public string Subject { get; set; }
-
- ///
- /// Name of the template to parse
- ///
- public string TemplateName { get; private set; }
-
- ///
- /// Whom to send to (TODO: is accountId OK?)
- ///
- public string To { get; set; }
- }
+using System;
+
+namespace Coderr.Server.Api.Core.Messaging.Commands
+{
+ ///
+ /// Send email using a template.
+ ///
+ [Message]
+ public class SendTemplateEmail
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// Mail title (i.e. not the subject)
+ ///
+ /// Template to load (should be a sub folder to the invoking class, look at
+ /// RequestPasswordResetHandler for an example.
+ ///
+ ///
+ public SendTemplateEmail(string mailTitle, string templateName)
+ {
+ if (mailTitle == null) throw new ArgumentNullException("mailTitle");
+ if (templateName == null) throw new ArgumentNullException("templateName");
+
+ MailTitle = mailTitle;
+ TemplateName = templateName;
+ }
+
+ ///
+ /// Serialization constructor
+ ///
+ protected SendTemplateEmail()
+ {
+ }
+
+ ///
+ /// Mail title (in the layout template)
+ ///
+ public string MailTitle { get; set; }
+
+ ///
+ /// View model
+ ///
+ public object Model { get; set; }
+
+ ///
+ /// Resources to use in the template
+ ///
+ public EmailResource[] Resources { get; set; }
+
+ ///
+ /// Mail subject.
+ ///
+ public string Subject { get; set; }
+
+ ///
+ /// Name of the template to parse
+ ///
+ public string TemplateName { get; private set; }
+
+ ///
+ /// Whom to send to (TODO: is accountId OK?)
+ ///
+ public string To { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Messaging/EmailAddress.cs b/src/Server/Coderr.Server.Api/Core/Messaging/EmailAddress.cs
similarity index 93%
rename from src/Server/OneTrueError.Api/Core/Messaging/EmailAddress.cs
rename to src/Server/Coderr.Server.Api/Core/Messaging/EmailAddress.cs
index d33877bd..e8a4ef96 100644
--- a/src/Server/OneTrueError.Api/Core/Messaging/EmailAddress.cs
+++ b/src/Server/Coderr.Server.Api/Core/Messaging/EmailAddress.cs
@@ -1,44 +1,44 @@
-using System;
-using System.ComponentModel.DataAnnotations;
-
-namespace OneTrueError.Api.Core.Messaging
-{
- ///
- /// Email address
- ///
- public class EmailAddress
- {
- ///
- /// Creates a new instance of .
- ///
- /// email address or account id
- public EmailAddress(string address)
- {
- if (address == null) throw new ArgumentNullException("address");
-
- var attr = new EmailAddressAttribute();
- int accountId;
- if (!attr.IsValid(address) && !int.TryParse(address, out accountId))
- throw new FormatException("'" + address + "' is not a valid email or account id.");
-
- Address = address;
- }
-
- ///
- /// Serialization constructor
- ///
- protected EmailAddress()
- {
- }
-
- ///
- /// Email address or AccountId.
- ///
- public string Address { get; set; }
-
- ///
- /// Recipient name
- ///
- public string Name { get; set; }
- }
+using System;
+using System.ComponentModel.DataAnnotations;
+
+namespace Coderr.Server.Api.Core.Messaging
+{
+ ///
+ /// Email address
+ ///
+ public class EmailAddress
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// email address or account id
+ public EmailAddress(string address)
+ {
+ if (address == null) throw new ArgumentNullException("address");
+
+ var attr = new EmailAddressAttribute();
+ int accountId;
+ if (!attr.IsValid(address) && !int.TryParse(address, out accountId))
+ throw new FormatException("'" + address + "' is not a valid email or account id.");
+
+ Address = address;
+ }
+
+ ///
+ /// Serialization constructor
+ ///
+ protected EmailAddress()
+ {
+ }
+
+ ///
+ /// Email address or AccountId.
+ ///
+ public string Address { get; set; }
+
+ ///
+ /// Recipient name
+ ///
+ public string Name { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Messaging/EmailMessage.cs b/src/Server/Coderr.Server.Api/Core/Messaging/EmailMessage.cs
similarity index 92%
rename from src/Server/OneTrueError.Api/Core/Messaging/EmailMessage.cs
rename to src/Server/Coderr.Server.Api/Core/Messaging/EmailMessage.cs
index d0bcfc90..e69a6ef3 100644
--- a/src/Server/OneTrueError.Api/Core/Messaging/EmailMessage.cs
+++ b/src/Server/Coderr.Server.Api/Core/Messaging/EmailMessage.cs
@@ -1,74 +1,79 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace OneTrueError.Api.Core.Messaging
-{
- ///
- /// Used to send emails.
- ///
- ///
- ///
- /// Used instead of the .NET classes to allow third party email services.
- ///
- ///
- public class EmailMessage
- {
- ///
- /// Create a new instance of
- ///
- public EmailMessage()
- {
- Resources = new List();
- }
-
- ///
- /// Create a new instance of
- ///
- /// Destination
- public EmailMessage(string recipient)
- {
- if (recipient == null) throw new ArgumentNullException("recipient");
- Recipients = new[] {new EmailAddress(recipient)};
- Resources = new List();
- }
-
- ///
- /// Create a new instance of
- ///
- /// List of recipients
- public EmailMessage(IReadOnlyList recipients)
- {
- if (recipients == null) throw new ArgumentNullException("recipients");
- if (recipients.Count == 0) throw new ArgumentException("Tried to send to an empty list.", "recipients");
-
- Recipients = recipients.Select(x => new EmailAddress(x)).ToArray();
- Resources = new List();
- }
-
- ///
- /// Body (should be send as HTML)
- ///
- public string HtmlBody { get; set; }
-
- ///
- /// List of recipients
- ///
- public EmailAddress[] Recipients { get; set; }
-
- ///
- /// Attachments and/or inline images.
- ///
- public IList Resources { get; set; }
-
- ///
- /// Subject line
- ///
- public string Subject { get; set; }
-
- ///
- /// Text body
- ///
- public string TextBody { get; set; }
- }
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Coderr.Server.Api.Core.Messaging
+{
+ ///
+ /// Used to send emails.
+ ///
+ ///
+ ///
+ /// Used instead of the .NET classes to allow third party email services.
+ ///
+ ///
+ public class EmailMessage
+ {
+ ///
+ /// Create a new instance of
+ ///
+ public EmailMessage()
+ {
+ Resources = new List();
+ }
+
+ ///
+ /// Create a new instance of
+ ///
+ /// Destination
+ public EmailMessage(string recipient)
+ {
+ if (recipient == null) throw new ArgumentNullException("recipient");
+ Recipients = new[] {new EmailAddress(recipient)};
+ Resources = new List();
+ }
+
+ ///
+ /// Create a new instance of
+ ///
+ /// List of recipients
+ public EmailMessage(IReadOnlyList recipients)
+ {
+ if (recipients == null) throw new ArgumentNullException("recipients");
+ if (recipients.Count == 0) throw new ArgumentException("Tried to send to an empty list.", "recipients");
+
+ Recipients = recipients.Select(x => new EmailAddress(x)).ToArray();
+ Resources = new List();
+ }
+
+ ///
+ /// Body (should be send as HTML)
+ ///
+ public string HtmlBody { get; set; }
+
+ ///
+ /// List of recipients
+ ///
+ public EmailAddress[] Recipients { get; set; }
+
+ ///
+ /// Whom should replies be sent to.
+ ///
+ public EmailAddress ReplyTo { get; set; }
+
+ ///
+ /// Attachments and/or inline images.
+ ///
+ public IList Resources { get; set; }
+
+ ///
+ /// Subject line
+ ///
+ public string Subject { get; set; }
+
+ ///
+ /// Text body
+ ///
+ public string TextBody { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Messaging/EmailResource.cs b/src/Server/Coderr.Server.Api/Core/Messaging/EmailResource.cs
similarity index 84%
rename from src/Server/OneTrueError.Api/Core/Messaging/EmailResource.cs
rename to src/Server/Coderr.Server.Api/Core/Messaging/EmailResource.cs
index ea778d1e..7b72dee7 100644
--- a/src/Server/OneTrueError.Api/Core/Messaging/EmailResource.cs
+++ b/src/Server/Coderr.Server.Api/Core/Messaging/EmailResource.cs
@@ -1,41 +1,41 @@
-using System;
-using System.IO;
-
-namespace OneTrueError.Api.Core.Messaging
-{
- ///
- /// A resource attached to an email (typically an image)
- ///
- public class EmailResource
- {
- ///
- /// Name of the resource (refered to using a cid in the email body)
- ///
- /// CID
- /// Actual content
- public EmailResource(string name, Stream content)
- {
- if (name == null) throw new ArgumentNullException("name");
- if (content == null) throw new ArgumentNullException("content");
- Name = name;
- Content = content;
- }
-
- ///
- /// Serialization constructor
- ///
- protected EmailResource()
- {
- }
-
- ///
- /// Contents of the resource. Stream must be readable.
- ///
- public Stream Content { get; set; }
-
- ///
- /// CID
- ///
- public string Name { get; set; }
- }
+using System;
+using System.IO;
+
+namespace Coderr.Server.Api.Core.Messaging
+{
+ ///
+ /// A resource attached to an email (typically an image)
+ ///
+ public class EmailResource
+ {
+ ///
+ /// Name of the resource (refered to using a cid in the email body)
+ ///
+ /// CID
+ /// Actual content
+ public EmailResource(string name, byte[] content)
+ {
+ if (name == null) throw new ArgumentNullException("name");
+ if (content == null) throw new ArgumentNullException("content");
+ Name = name;
+ Content = content;
+ }
+
+ ///
+ /// Serialization constructor
+ ///
+ protected EmailResource()
+ {
+ }
+
+ ///
+ /// Contents of the resource. Stream must be readable.
+ ///
+ public byte[] Content { get; set; }
+
+ ///
+ /// CID
+ ///
+ public string Name { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Messaging/NamespaceDoc.cs b/src/Server/Coderr.Server.Api/Core/Messaging/NamespaceDoc.cs
new file mode 100644
index 00000000..a5c28721
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Messaging/NamespaceDoc.cs
@@ -0,0 +1,16 @@
+using System.Runtime.CompilerServices;
+
+namespace Coderr.Server.Api.Core.Messaging
+{
+ // This file is Generated by the tool MarkdownToNamespaceDoc. ReadMe.md is the master.
+
+ ///
+ /// Messaging, which includes sending emails.
+ ///
+ ///
+ ///
+ [CompilerGenerated]
+ internal class NamespaceDoc
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Messaging/ReadMe.md b/src/Server/Coderr.Server.Api/Core/Messaging/ReadMe.md
similarity index 100%
rename from src/Server/OneTrueError.Api/Core/Messaging/ReadMe.md
rename to src/Server/Coderr.Server.Api/Core/Messaging/ReadMe.md
diff --git a/src/Server/Coderr.Server.Api/Core/NamespaceDoc.cs b/src/Server/Coderr.Server.Api/Core/NamespaceDoc.cs
new file mode 100644
index 00000000..6906fff7
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/NamespaceDoc.cs
@@ -0,0 +1,17 @@
+using System.Runtime.CompilerServices;
+
+namespace Coderr.Server.Api.Core
+{
+ // This file is Generated by the tool MarkdownToNamespaceDoc. ReadMe.md is the master.
+
+ ///
+ /// Core
+ ///
+ ///
+ /// Core contains all basic functionality to get Coderr running. A minimal set of analysis is done here.
+ ///
+ [CompilerGenerated]
+ internal class NamespaceDoc
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Notifications/AddNotification.cs b/src/Server/Coderr.Server.Api/Core/Notifications/AddNotification.cs
new file mode 100644
index 00000000..0a2bbc8b
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Notifications/AddNotification.cs
@@ -0,0 +1,99 @@
+using System;
+
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Local
+
+namespace Coderr.Server.Api.Core.Notifications
+{
+ ///
+ /// Add a user notification
+ ///
+ ///
+ ///
+ /// User notifications are typically used when the user need to do some action (typically due to configuration
+ /// issues).
+ ///
+ ///
+ [Message]
+ public class AddNotification
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// user account id
+ /// message to display
+ public AddNotification(int accountId, string message)
+ {
+ if (accountId <= 0) throw new ArgumentOutOfRangeException("accountId");
+
+ Message = message ?? throw new ArgumentNullException("message");
+ AccountId = accountId;
+ }
+
+ ///
+ /// Creates a new instance of .
+ ///
+ /// Send this message to first user that logs in with the specified role
+ /// Message to display to the user
+ public AddNotification(string roleName, string message)
+ {
+ RoleName = roleName ?? throw new ArgumentNullException("roleName");
+ Message = message ?? throw new ArgumentNullException("message");
+ }
+
+ ///
+ /// Serialization constructor
+ ///
+ protected AddNotification()
+ {
+
+ }
+
+ ///
+ /// Display only for the specified user.
+ ///
+ public int? AccountId { get; private set; }
+
+
+ ///
+ /// Amount of time to wait until creating this notification again once the user have read the notification.
+ ///
+ ///
+ ///
+ /// Requires to be set.
+ ///
+ ///
+ public TimeSpan? HoldbackInterval { get; set; }
+
+ ///
+ /// Message to display to user
+ ///
+ public string Message { get; private set; }
+
+ ///
+ /// There may only exist one notification of each type for the target user(s).
+ ///
+ ///
+ ///
+ /// Set this to a unique value for your module if you want to prevent multiple instances of the same notification
+ /// to be created. Useful for instance if you sent a configuration failure message when a new report is created.
+ /// Without this type, the same notification would be created every time a report arrives until the configuration
+ /// have been corrected.
+ ///
+ ///
+ /// The notification will be sent again when the user have read it, unless you also have set the hold-back
+ /// timespan.
+ ///
+ ///
+ public string NotificationType { get; set; }
+
+ ///
+ /// Display this message for everyone with the given role
+ ///
+ ///
+ ///
+ /// Alternative to .
+ ///
+ ///
+ public string RoleName { get; private set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/ReadMe.md b/src/Server/Coderr.Server.Api/Core/ReadMe.md
new file mode 100644
index 00000000..c307b3d5
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/ReadMe.md
@@ -0,0 +1,4 @@
+Core
+============
+
+Core contains all basic functionality to get codeRR running. A minimal set of analysis is done here.
diff --git a/src/Server/Coderr.Server.Api/Core/Reports/ContextCollectionDTO.cs b/src/Server/Coderr.Server.Api/Core/Reports/ContextCollectionDTO.cs
new file mode 100644
index 00000000..38eed818
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Reports/ContextCollectionDTO.cs
@@ -0,0 +1,58 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Coderr.Server.Api.Core.Reports
+{
+ ///
+ /// Context collection DTO.
+ ///
+ public class ContextCollectionDTO
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ protected ContextCollectionDTO()
+ {
+ }
+
+ ///
+ /// Creates a new instance of .
+ ///
+ /// Name as specified in the client library
+ /// Properties.
+ public ContextCollectionDTO(string name, IDictionary items)
+ {
+ if (name == null) throw new ArgumentNullException("name");
+ if (items == null) throw new ArgumentNullException("items");
+
+ Name = name;
+ Properties = items;
+ }
+
+
+ ///
+ /// Name as specified in the client library
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// Properties.
+ ///
+ public IDictionary Properties { get; set; }
+
+ ///
+ /// Returns a string that represents the current object.
+ ///
+ ///
+ /// A string that represents the current object.
+ ///
+ /// 2
+ public override string ToString()
+ {
+ var flatten = Properties.Select(x => x.Key + "=" + x.Value);
+ var joinProps = string.Join(", ", flatten);
+ return string.Format("{0} [{1}]", Name, joinProps);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Reports/NamespaceDoc.cs b/src/Server/Coderr.Server.Api/Core/Reports/NamespaceDoc.cs
new file mode 100644
index 00000000..0b119288
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Reports/NamespaceDoc.cs
@@ -0,0 +1,16 @@
+using System.Runtime.CompilerServices;
+
+namespace Coderr.Server.Api.Core.Reports
+{
+ // This file is Generated by the tool MarkdownToNamespaceDoc. ReadMe.md is the master.
+
+ ///
+ /// Reports represent the recieved exception along with all collected context information.
+ ///
+ ///
+ ///
+ [CompilerGenerated]
+ internal class NamespaceDoc
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Reports/Queries/GetReport.cs b/src/Server/Coderr.Server.Api/Core/Reports/Queries/GetReport.cs
similarity index 91%
rename from src/Server/OneTrueError.Api/Core/Reports/Queries/GetReport.cs
rename to src/Server/Coderr.Server.Api/Core/Reports/Queries/GetReport.cs
index a26ef7c4..9558299b 100644
--- a/src/Server/OneTrueError.Api/Core/Reports/Queries/GetReport.cs
+++ b/src/Server/Coderr.Server.Api/Core/Reports/Queries/GetReport.cs
@@ -1,34 +1,35 @@
-using System;
-using DotNetCqs;
-
-namespace OneTrueError.Api.Core.Reports.Queries
-{
- ///
- /// Get report (i.e. exception and context collections)
- ///
- public class GetReport : Query
- {
- ///
- /// Serialization constructor.
- ///
- protected GetReport()
- {
- }
-
- ///
- /// Creates a new instance of .
- ///
- /// report
- /// reportId
- public GetReport(int reportId)
- {
- if (reportId <= 0) throw new ArgumentOutOfRangeException("reportId");
- ReportId = reportId;
- }
-
- ///
- /// Report id
- ///
- public int ReportId { get; private set; }
- }
+using System;
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Core.Reports.Queries
+{
+ ///
+ /// Get report (i.e. exception and context collections)
+ ///
+ [Message]
+ public class GetReport : Query
+ {
+ ///
+ /// Serialization constructor.
+ ///
+ protected GetReport()
+ {
+ }
+
+ ///
+ /// Creates a new instance of .
+ ///
+ /// report
+ /// reportId
+ public GetReport(int reportId)
+ {
+ if (reportId <= 0) throw new ArgumentOutOfRangeException("reportId");
+ ReportId = reportId;
+ }
+
+ ///
+ /// Report id
+ ///
+ public int ReportId { get; private set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Reports/Queries/GetReportException.cs b/src/Server/Coderr.Server.Api/Core/Reports/Queries/GetReportException.cs
similarity index 93%
rename from src/Server/OneTrueError.Api/Core/Reports/Queries/GetReportException.cs
rename to src/Server/Coderr.Server.Api/Core/Reports/Queries/GetReportException.cs
index c93b2190..ffd29637 100644
--- a/src/Server/OneTrueError.Api/Core/Reports/Queries/GetReportException.cs
+++ b/src/Server/Coderr.Server.Api/Core/Reports/Queries/GetReportException.cs
@@ -1,53 +1,53 @@
-namespace OneTrueError.Api.Core.Reports.Queries
-{
- ///
- /// Partial result for .
- ///
- public class GetReportException
- {
- ///
- /// Assembly that the exception type is declared in.
- ///
- public string AssemblyName { get; set; }
-
- ///
- /// Base class names (without namespace). At least "Exception".
- ///
- public string[] BaseClasses { get; set; }
-
- ///
- /// Typically exception.ToString()
- ///
- public string Everything { get; set; }
-
- ///
- /// Full type name
- ///
- public string FullName { get; set; }
-
- ///
- /// Inner exception (or null)
- ///
- public GetReportException InnerException { get; set; }
-
- ///
- /// Exception.Message
- ///
- public string Message { get; set; }
-
- ///
- /// Exception name (first line of the exception message)
- ///
- public string Name { get; set; }
-
- ///
- /// Type namespace
- ///
- public string Namespace { get; set; }
-
- ///
- /// Stack trace.
- ///
- public string StackTrace { get; set; }
- }
+namespace Coderr.Server.Api.Core.Reports.Queries
+{
+ ///
+ /// Partial result for .
+ ///
+ public class GetReportException
+ {
+ ///
+ /// Assembly that the exception type is declared in.
+ ///
+ public string AssemblyName { get; set; }
+
+ ///
+ /// Base class names (without namespace). At least "Exception".
+ ///
+ public string[] BaseClasses { get; set; }
+
+ ///
+ /// Typically exception.ToString()
+ ///
+ public string Everything { get; set; }
+
+ ///
+ /// Full type name
+ ///
+ public string FullName { get; set; }
+
+ ///
+ /// Inner exception (or null)
+ ///
+ public GetReportException InnerException { get; set; }
+
+ ///
+ /// Exception.Message
+ ///
+ public string Message { get; set; }
+
+ ///
+ /// Exception name (first line of the exception message)
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// Type namespace
+ ///
+ public string Namespace { get; set; }
+
+ ///
+ /// Stack trace.
+ ///
+ public string StackTrace { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Reports/Queries/GetReportList.cs b/src/Server/Coderr.Server.Api/Core/Reports/Queries/GetReportList.cs
similarity index 91%
rename from src/Server/OneTrueError.Api/Core/Reports/Queries/GetReportList.cs
rename to src/Server/Coderr.Server.Api/Core/Reports/Queries/GetReportList.cs
index 1f6f401f..79e5beec 100644
--- a/src/Server/OneTrueError.Api/Core/Reports/Queries/GetReportList.cs
+++ b/src/Server/Coderr.Server.Api/Core/Reports/Queries/GetReportList.cs
@@ -1,44 +1,45 @@
-using System;
-using DotNetCqs;
-
-namespace OneTrueError.Api.Core.Reports.Queries
-{
- ///
- /// Get reports
- ///
- public class GetReportList : Query
- {
- ///
- /// Get reports
- ///
- /// incident to get reports for
- public GetReportList(int incidentId)
- {
- if (incidentId <= 0) throw new ArgumentOutOfRangeException("incidentId");
- IncidentId = incidentId;
- }
-
- ///
- /// Serialization constructor.
- ///
- protected GetReportList()
- {
- }
-
-
- ///
- /// Incident id.
- ///
- public int IncidentId { get; private set; }
-
- ///
- /// Page number (one based index)
- ///
- public int PageNumber { get; set; }
-
- ///
- /// Page size (default is 20).
- ///
- public int PageSize { get; set; }
- }
+using System;
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Core.Reports.Queries
+{
+ ///
+ /// Get reports
+ ///
+ [Message]
+ public class GetReportList : Query
+ {
+ ///
+ /// Get reports
+ ///
+ /// incident to get reports for
+ public GetReportList(int incidentId)
+ {
+ if (incidentId <= 0) throw new ArgumentOutOfRangeException("incidentId");
+ IncidentId = incidentId;
+ }
+
+ ///
+ /// Serialization constructor.
+ ///
+ protected GetReportList()
+ {
+ }
+
+
+ ///
+ /// Incident id.
+ ///
+ public int IncidentId { get; private set; }
+
+ ///
+ /// Page number (one based index)
+ ///
+ public int PageNumber { get; set; }
+
+ ///
+ /// Page size (default is 20).
+ ///
+ public int PageSize { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Reports/Queries/GetReportListResult.cs b/src/Server/Coderr.Server.Api/Core/Reports/Queries/GetReportListResult.cs
similarity index 93%
rename from src/Server/OneTrueError.Api/Core/Reports/Queries/GetReportListResult.cs
rename to src/Server/Coderr.Server.Api/Core/Reports/Queries/GetReportListResult.cs
index 68a0aedb..59b2bfd5 100644
--- a/src/Server/OneTrueError.Api/Core/Reports/Queries/GetReportListResult.cs
+++ b/src/Server/Coderr.Server.Api/Core/Reports/Queries/GetReportListResult.cs
@@ -1,48 +1,48 @@
-using System;
-
-namespace OneTrueError.Api.Core.Reports.Queries
-{
- ///
- /// Result for .
- ///
- public class GetReportListResult
- {
- ///
- /// Creates a new instance of .
- ///
- /// Result items
- /// items
- public GetReportListResult(GetReportListResultItem[] items)
- {
- if (items == null) throw new ArgumentNullException("items");
- Items = items;
- }
-
- ///
- /// Serialization constructor.
- ///
- protected GetReportListResult()
- {
- }
-
- ///
- /// Items on this page.
- ///
- public GetReportListResultItem[] Items { get; set; }
-
- ///
- /// Page number being returned
- ///
- public int PageNumber { get; set; }
-
- ///
- /// Number of items on this page
- ///
- public int PageSize { get; set; }
-
- ///
- /// Total number of items that a non-paged query would return
- ///
- public int TotalCount { get; set; }
- }
+using System;
+
+namespace Coderr.Server.Api.Core.Reports.Queries
+{
+ ///
+ /// Result for .
+ ///
+ public class GetReportListResult
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// Result items
+ /// items
+ public GetReportListResult(GetReportListResultItem[] items)
+ {
+ if (items == null) throw new ArgumentNullException("items");
+ Items = items;
+ }
+
+ ///
+ /// Serialization constructor.
+ ///
+ protected GetReportListResult()
+ {
+ }
+
+ ///
+ /// Items on this page.
+ ///
+ public GetReportListResultItem[] Items { get; set; }
+
+ ///
+ /// Page number being returned
+ ///
+ public int PageNumber { get; set; }
+
+ ///
+ /// Number of items on this page
+ ///
+ public int PageSize { get; set; }
+
+ ///
+ /// Total number of items that a non-paged query would return
+ ///
+ public int TotalCount { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Reports/Queries/GetReportListResultItem.cs b/src/Server/Coderr.Server.Api/Core/Reports/Queries/GetReportListResultItem.cs
similarity index 90%
rename from src/Server/OneTrueError.Api/Core/Reports/Queries/GetReportListResultItem.cs
rename to src/Server/Coderr.Server.Api/Core/Reports/Queries/GetReportListResultItem.cs
index 7cc0b54d..0e07a0a4 100644
--- a/src/Server/OneTrueError.Api/Core/Reports/Queries/GetReportListResultItem.cs
+++ b/src/Server/Coderr.Server.Api/Core/Reports/Queries/GetReportListResultItem.cs
@@ -1,30 +1,30 @@
-using System;
-
-namespace OneTrueError.Api.Core.Reports.Queries
-{
- ///
- /// Item for .
- ///
- public class GetReportListResultItem
- {
- ///
- /// When the report was created in the client library
- ///
- public DateTime CreatedAtUtc { get; set; }
-
- ///
- /// Report id
- ///
- public int Id { get; set; }
-
- ///
- /// Exception message.
- ///
- public string Message { get; set; }
-
- ///
- /// IP that uploaded the report.
- ///
- public string RemoteAddress { get; set; }
- }
+using System;
+
+namespace Coderr.Server.Api.Core.Reports.Queries
+{
+ ///
+ /// Item for .
+ ///
+ public class GetReportListResultItem
+ {
+ ///
+ /// When the report was created in the client library
+ ///
+ public DateTime CreatedAtUtc { get; set; }
+
+ ///
+ /// Report id
+ ///
+ public int Id { get; set; }
+
+ ///
+ /// Exception message.
+ ///
+ public string Message { get; set; }
+
+ ///
+ /// IP that uploaded the report.
+ ///
+ public string RemoteAddress { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Reports/Queries/GetReportResult.cs b/src/Server/Coderr.Server.Api/Core/Reports/Queries/GetReportResult.cs
similarity index 93%
rename from src/Server/OneTrueError.Api/Core/Reports/Queries/GetReportResult.cs
rename to src/Server/Coderr.Server.Api/Core/Reports/Queries/GetReportResult.cs
index 993510f9..a72ddd41 100644
--- a/src/Server/OneTrueError.Api/Core/Reports/Queries/GetReportResult.cs
+++ b/src/Server/Coderr.Server.Api/Core/Reports/Queries/GetReportResult.cs
@@ -1,60 +1,60 @@
-using System;
-
-namespace OneTrueError.Api.Core.Reports.Queries
-{
- ///
- /// Result for .
- ///
- public class GetReportResult
- {
- ///
- /// Context collections
- ///
- public GetReportResultContextCollection[] ContextCollections { get; set; }
-
- ///
- /// When the report was created in the client library
- ///
- public DateTime CreatedAtUtc { get; set; }
-
- ///
- /// Email address (if the user would like to get status updates).
- ///
- public string EmailAddress { get; set; }
-
- ///
- /// Unique id generated in the client library
- ///
- public string ErrorId { get; set; }
-
- ///
- /// Actual exception
- ///
- public GetReportException Exception { get; set; }
-
- ///
- /// Report id
- ///
- public string Id { get; set; }
-
- ///
- /// Incident that this report belongs to.
- ///
- public string IncidentId { get; set; }
-
- ///
- /// First line from the exception message.
- ///
- public string Message { get; set; }
-
- ///
- /// Stack trace
- ///
- public string StackTrace { get; set; }
-
- ///
- /// Error description written by the user (if any).
- ///
- public string UserFeedback { get; set; }
- }
+using System;
+
+namespace Coderr.Server.Api.Core.Reports.Queries
+{
+ ///
+ /// Result for .
+ ///
+ public class GetReportResult
+ {
+ ///
+ /// Context collections
+ ///
+ public GetReportResultContextCollection[] ContextCollections { get; set; }
+
+ ///
+ /// When the report was created in the client library
+ ///
+ public DateTime CreatedAtUtc { get; set; }
+
+ ///
+ /// Email address (if the user would like to get status updates).
+ ///
+ public string EmailAddress { get; set; }
+
+ ///
+ /// Unique id generated in the client library
+ ///
+ public string ErrorId { get; set; }
+
+ ///
+ /// Actual exception
+ ///
+ public GetReportException Exception { get; set; }
+
+ ///
+ /// Report id
+ ///
+ public string Id { get; set; }
+
+ ///
+ /// Incident that this report belongs to.
+ ///
+ public string IncidentId { get; set; }
+
+ ///
+ /// First line from the exception message.
+ ///
+ public string Message { get; set; }
+
+ ///
+ /// Stack trace
+ ///
+ public string StackTrace { get; set; }
+
+ ///
+ /// Error description written by the user (if any).
+ ///
+ public string UserFeedback { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Reports/Queries/GetReportResultContextCollection.cs b/src/Server/Coderr.Server.Api/Core/Reports/Queries/GetReportResultContextCollection.cs
similarity index 93%
rename from src/Server/OneTrueError.Api/Core/Reports/Queries/GetReportResultContextCollection.cs
rename to src/Server/Coderr.Server.Api/Core/Reports/Queries/GetReportResultContextCollection.cs
index fd06bb94..05b10c7e 100644
--- a/src/Server/OneTrueError.Api/Core/Reports/Queries/GetReportResultContextCollection.cs
+++ b/src/Server/Coderr.Server.Api/Core/Reports/Queries/GetReportResultContextCollection.cs
@@ -1,42 +1,42 @@
-using System;
-
-namespace OneTrueError.Api.Core.Reports.Queries
-{
- ///
- /// Context collection for .
- ///
- public class GetReportResultContextCollection
- {
- ///
- /// Creates a new instance of .
- ///
- /// collection name
- /// all uploaded properties
- /// name; properties
- public GetReportResultContextCollection(string name, KeyValuePair[] properties)
- {
- if (name == null) throw new ArgumentNullException("name");
- if (properties == null) throw new ArgumentNullException("properties");
-
- Name = name;
- Properties = properties;
- }
-
- ///
- /// Serialization constructor.
- ///
- protected GetReportResultContextCollection()
- {
- }
-
- ///
- /// Context collection name
- ///
- public string Name { get; set; }
-
- ///
- /// Properties.
- ///
- public KeyValuePair[] Properties { get; set; }
- }
+using System;
+
+namespace Coderr.Server.Api.Core.Reports.Queries
+{
+ ///
+ /// Context collection for .
+ ///
+ public class GetReportResultContextCollection
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// collection name
+ /// all uploaded properties
+ /// name; properties
+ public GetReportResultContextCollection(string name, KeyValuePair[] properties)
+ {
+ if (name == null) throw new ArgumentNullException("name");
+ if (properties == null) throw new ArgumentNullException("properties");
+
+ Name = name;
+ Properties = properties;
+ }
+
+ ///
+ /// Serialization constructor.
+ ///
+ protected GetReportResultContextCollection()
+ {
+ }
+
+ ///
+ /// Context collection name
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// Properties.
+ ///
+ public KeyValuePair[] Properties { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Reports/Queries/KeyValuePair.cs b/src/Server/Coderr.Server.Api/Core/Reports/Queries/KeyValuePair.cs
similarity index 91%
rename from src/Server/OneTrueError.Api/Core/Reports/Queries/KeyValuePair.cs
rename to src/Server/Coderr.Server.Api/Core/Reports/Queries/KeyValuePair.cs
index 208a8c6a..f27dbd03 100644
--- a/src/Server/OneTrueError.Api/Core/Reports/Queries/KeyValuePair.cs
+++ b/src/Server/Coderr.Server.Api/Core/Reports/Queries/KeyValuePair.cs
@@ -1,41 +1,41 @@
-using System;
-
-namespace OneTrueError.Api.Core.Reports.Queries
-{
- ///
- /// Key value pair
- ///
- public class KeyValuePair
- {
- ///
- /// Creates a new instance of .
- ///
- /// key
- /// value (null is allowed)
- /// key; value
- public KeyValuePair(string key, string value)
- {
- if (key == null) throw new ArgumentNullException("key");
-
- Key = key;
- Value = value;
- }
-
- ///
- /// Serialization constructor
- ///
- protected KeyValuePair()
- {
- }
-
- ///
- /// Key
- ///
- public string Key { get; private set; }
-
- ///
- /// Value
- ///
- public string Value { get; private set; }
- }
+using System;
+
+namespace Coderr.Server.Api.Core.Reports.Queries
+{
+ ///
+ /// Key value pair
+ ///
+ public class KeyValuePair
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// key
+ /// value (null is allowed)
+ /// key; value
+ public KeyValuePair(string key, string value)
+ {
+ if (key == null) throw new ArgumentNullException("key");
+
+ Key = key;
+ Value = value;
+ }
+
+ ///
+ /// Serialization constructor
+ ///
+ protected KeyValuePair()
+ {
+ }
+
+ ///
+ /// Key
+ ///
+ public string Key { get; private set; }
+
+ ///
+ /// Value
+ ///
+ public string Value { get; private set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Reports/ReadMe.md b/src/Server/Coderr.Server.Api/Core/Reports/ReadMe.md
similarity index 100%
rename from src/Server/OneTrueError.Api/Core/Reports/ReadMe.md
rename to src/Server/Coderr.Server.Api/Core/Reports/ReadMe.md
diff --git a/src/Server/Coderr.Server.Api/Core/Reports/ReportDTO.cs b/src/Server/Coderr.Server.Api/Core/Reports/ReportDTO.cs
new file mode 100644
index 00000000..175b1f3e
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Reports/ReportDTO.cs
@@ -0,0 +1,55 @@
+using System;
+
+namespace Coderr.Server.Api.Core.Reports
+{
+ ///
+ /// Report representation.
+ ///
+ public class ReportDTO
+ {
+ ///
+ /// Application that the incident and report belongs in.
+ ///
+ public int ApplicationId { get; set; }
+
+ ///
+ /// A collection of context information such as HTTP request information or computer hardware info.
+ ///
+ public ContextCollectionDTO[] ContextCollections { get; set; }
+
+ ///
+ /// Date specified at client side
+ ///
+ public DateTime CreatedAtUtc { get; set; }
+
+ ///
+ /// Exception which was caught.
+ ///
+ public ReportExeptionDTO Exception { get; set; }
+
+ ///
+ /// DB primary key
+ ///
+ public int Id { get; set; }
+
+ ///
+ /// DB primary key
+ ///
+ public int IncidentId { get; set; }
+
+ ///
+ /// Ip of the report uploader.
+ ///
+ public string RemoteAddress { get; set; }
+
+ ///
+ /// Gets error id (unique identifier used in communication with the customer to identify this error)
+ ///
+ public string ReportId { get; set; }
+
+ ///
+ /// Version of the report
+ ///
+ public string ReportVersion { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Reports/ReportExeptionDTO.cs b/src/Server/Coderr.Server.Api/Core/Reports/ReportExeptionDTO.cs
new file mode 100644
index 00000000..b35c407a
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Reports/ReportExeptionDTO.cs
@@ -0,0 +1,70 @@
+using System;
+using System.Collections.Generic;
+
+namespace Coderr.Server.Api.Core.Reports
+{
+ ///
+ /// Model used to wrap all information from an exception.
+ ///
+ public class ReportExeptionDTO
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public ReportExeptionDTO()
+ {
+ Properties = new Dictionary(StringComparer.OrdinalIgnoreCase);
+ }
+
+ ///
+ /// Assembly name (version included)
+ ///
+ public string AssemblyName { get; set; }
+
+ ///
+ /// Exception base classes. Most specific first: ArgumentOutOfRangeException, ArgumentException,
+ /// Exception.
+ ///
+ public string[] BaseClasses { get; set; }
+
+ ///
+ /// Everything (exception.ToString())
+ ///
+ public string Everything { get; set; }
+
+ ///
+ /// Full type name (namespace + class name)
+ ///
+ public string FullName { get; set; }
+
+ ///
+ /// Inner exception (if any; otherwise null).
+ ///
+ public ReportExeptionDTO InnerException { get; set; }
+
+ ///
+ /// Exception message
+ ///
+ public string Message { get; set; }
+
+ ///
+ /// Type name
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// Namespace that the exception is in
+ ///
+ public string Namespace { get; set; }
+
+ ///
+ /// All properties (public and private)
+ ///
+ public IDictionary Properties { get; set; }
+
+ ///
+ /// Stack trace, line numbers included if your app also distributes the PDB files.
+ ///
+ public string StackTrace { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Reports/ReportExtensions.cs b/src/Server/Coderr.Server.Api/Core/Reports/ReportExtensions.cs
new file mode 100644
index 00000000..3a4bea7c
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Reports/ReportExtensions.cs
@@ -0,0 +1,25 @@
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Coderr.Server.Api.Core.Reports
+{
+ public static class ReportExtensions
+ {
+
+ public static ContextCollectionDTO GetCoderrCollection(
+ this IEnumerable instance)
+ {
+ return instance.FirstOrDefault(x => x.Name == "CoderrData");
+ }
+
+ public static ContextCollectionDTO GetCoderrCollection(
+ this ReportDTO instance)
+ {
+ return instance.ContextCollections.FirstOrDefault(x => x.Name == "CoderrData");
+ }
+
+
+
+ }
+
+}
diff --git a/src/Server/Coderr.Server.Api/Core/Settings/Commands/SaveAccountSetting.cs b/src/Server/Coderr.Server.Api/Core/Settings/Commands/SaveAccountSetting.cs
new file mode 100644
index 00000000..1f842c84
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Settings/Commands/SaveAccountSetting.cs
@@ -0,0 +1,11 @@
+namespace Coderr.Server.Api.Core.Settings.Commands
+{
+ [Command]
+ public class SaveAccountSetting
+ {
+ public int AccountId { get; set; }
+ public string Name { get; set; }
+ public string Value { get; set; }
+
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Settings/Commands/SaveAccountSettings.cs b/src/Server/Coderr.Server.Api/Core/Settings/Commands/SaveAccountSettings.cs
new file mode 100644
index 00000000..04af3421
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Settings/Commands/SaveAccountSettings.cs
@@ -0,0 +1,11 @@
+using System.Collections.Generic;
+
+namespace Coderr.Server.Api.Core.Settings.Commands
+{
+ [Command]
+ public class SaveAccountSettings
+ {
+ public int AccountId { get; set; }
+ public IDictionary Settings { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Settings/Queries/GetAccountSetting.cs b/src/Server/Coderr.Server.Api/Core/Settings/Queries/GetAccountSetting.cs
new file mode 100644
index 00000000..07dc0479
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Settings/Queries/GetAccountSetting.cs
@@ -0,0 +1,11 @@
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Core.Settings.Queries
+{
+ [Message]
+ public class GetAccountSetting : Query
+ {
+ public int AccountId { get; set; }
+ public string Name { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Settings/Queries/GetAccountSettingResult.cs b/src/Server/Coderr.Server.Api/Core/Settings/Queries/GetAccountSettingResult.cs
new file mode 100644
index 00000000..78c767b6
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Settings/Queries/GetAccountSettingResult.cs
@@ -0,0 +1,7 @@
+namespace Coderr.Server.Api.Core.Settings.Queries
+{
+ public class GetAccountSettingResult
+ {
+ public string Value { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Settings/Queries/GetAccountSettings.cs b/src/Server/Coderr.Server.Api/Core/Settings/Queries/GetAccountSettings.cs
new file mode 100644
index 00000000..e6fe412c
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Settings/Queries/GetAccountSettings.cs
@@ -0,0 +1,10 @@
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Core.Settings.Queries
+{
+ [Message]
+ public class GetAccountSettings : Query
+ {
+ public int AccountId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Settings/Queries/GetAccountSettingsResult.cs b/src/Server/Coderr.Server.Api/Core/Settings/Queries/GetAccountSettingsResult.cs
new file mode 100644
index 00000000..8acc42c9
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Settings/Queries/GetAccountSettingsResult.cs
@@ -0,0 +1,9 @@
+using System.Collections.Generic;
+
+namespace Coderr.Server.Api.Core.Settings.Queries
+{
+ public class GetAccountSettingsResult
+ {
+ public IDictionary Settings { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Support/NamespaceDoc.cs b/src/Server/Coderr.Server.Api/Core/Support/NamespaceDoc.cs
new file mode 100644
index 00000000..c43a865e
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Support/NamespaceDoc.cs
@@ -0,0 +1,16 @@
+using System.Runtime.CompilerServices;
+
+namespace Coderr.Server.Api.Core.Support
+{
+ // This file is Generated by the tool MarkdownToNamespaceDoc. ReadMe.md is the master.
+
+ ///
+ /// Used to get support from Gauffin Interactive AB
+ ///
+ ///
+ ///
+ [CompilerGenerated]
+ internal class NamespaceDoc
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Support/ReadMe.md b/src/Server/Coderr.Server.Api/Core/Support/ReadMe.md
similarity index 100%
rename from src/Server/OneTrueError.Api/Core/Support/ReadMe.md
rename to src/Server/Coderr.Server.Api/Core/Support/ReadMe.md
diff --git a/src/Server/Coderr.Server.Api/Core/Support/SendSupportRequest.cs b/src/Server/Coderr.Server.Api/Core/Support/SendSupportRequest.cs
new file mode 100644
index 00000000..e1709881
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Support/SendSupportRequest.cs
@@ -0,0 +1,24 @@
+namespace Coderr.Server.Api.Core.Support
+{
+ ///
+ /// Send a support request to 1TCompany AB
+ ///
+ [Message]
+ public class SendSupportRequest
+ {
+ ///
+ /// Problem statement
+ ///
+ public string Message { get; set; }
+
+ ///
+ /// Why do we want support, huh?
+ ///
+ public string Subject { get; set; }
+
+ ///
+ /// Url of the page that did not work
+ ///
+ public string Url { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Users/Commands/DeleteBrowserSubscription.cs b/src/Server/Coderr.Server.Api/Core/Users/Commands/DeleteBrowserSubscription.cs
new file mode 100644
index 00000000..bed2f178
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Users/Commands/DeleteBrowserSubscription.cs
@@ -0,0 +1,9 @@
+namespace Coderr.Server.Api.Core.Users.Commands
+{
+ [Message]
+ public class DeleteBrowserSubscription
+ {
+ public int UserId { get; set; }
+ public string Endpoint { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Users/Commands/StoreBrowserSubscription.cs b/src/Server/Coderr.Server.Api/Core/Users/Commands/StoreBrowserSubscription.cs
new file mode 100644
index 00000000..88d41326
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Users/Commands/StoreBrowserSubscription.cs
@@ -0,0 +1,17 @@
+namespace Coderr.Server.Api.Core.Users.Commands
+{
+ ///
+ /// https://tools.ietf.org/html/draft-ietf-webpush-encryption-08
+ ///
+ [Message]
+ public class StoreBrowserSubscription
+ {
+ public int UserId { get; set; }
+ public string Endpoint { get; set; }
+
+ public string PublicKey { get; set; }
+ public string AuthenticationSecret { get; set; }
+
+ public long? ExpirationTime { get; set; }
+ }
+}
diff --git a/src/Server/Coderr.Server.Api/Core/Users/Commands/UpdateNotifications.cs b/src/Server/Coderr.Server.Api/Core/Users/Commands/UpdateNotifications.cs
new file mode 100644
index 00000000..0ad0a4ea
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Users/Commands/UpdateNotifications.cs
@@ -0,0 +1,50 @@
+namespace Coderr.Server.Api.Core.Users.Commands
+{
+ ///
+ /// Update user notifications
+ ///
+ [Message]
+ public class UpdateNotifications
+ {
+ ///
+ /// Application that the settings is for (0 = general settings)
+ ///
+ public int ApplicationId { get; set; }
+
+ ///
+ /// How to notify when a new incident is created (received an unique exception)
+ ///
+ public NotificationState NotifyOnNewIncidents { get; set; }
+
+ ///
+ /// How to notify when an incident is updated to critical.
+ ///
+ public NotificationState NotifyOnCriticalIncidents { get; set; }
+
+ ///
+ /// How to notify when an incident is updated to important.
+ ///
+ public NotificationState NotifyOnImportantIncidents { get; set; }
+
+ ///
+ /// How to notify user when a peak is detected
+ ///
+ public NotificationState NotifyOnPeaks { get; set; }
+
+ ///
+ /// How to notify when we receive a new report on a closed incident.
+ ///
+ public NotificationState NotifyOnReOpenedIncident { get; set; }
+
+ ///
+ /// How to notify when an user have written an error description
+ ///
+ public NotificationState NotifyOnUserFeedback { get; set; }
+
+
+ ///
+ /// User that configured its settings.
+ ///
+ public int UserId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Users/Commands/UpdatePersonalSettings.cs b/src/Server/Coderr.Server.Api/Core/Users/Commands/UpdatePersonalSettings.cs
new file mode 100644
index 00000000..2d51c4fc
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Users/Commands/UpdatePersonalSettings.cs
@@ -0,0 +1,41 @@
+namespace Coderr.Server.Api.Core.Users.Commands
+{
+ ///
+ /// Update personal settings.
+ ///
+ [Message]
+ public class UpdatePersonalSettings
+ {
+ ///
+ /// Change email address
+ ///
+ ///
+ ///
+ /// Do not required additional verification, we trust the user once it has an activated account.
+ ///
+ ///
+ public string EmailAddress { get; set; }
+
+ ///
+ /// First name (if specified)
+ ///
+ public string FirstName { get; set; }
+
+
+ ///
+ /// Last name (if specified)
+ ///
+ public string LastName { get; set; }
+
+ ///
+ /// Mobile number (E.164 formatted)
+ ///
+ public string MobileNumber { get; set; }
+
+ ///
+ /// Account that the settings are for
+ ///
+ [IgnoreField]
+ public int UserId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Users/NamespaceDoc.cs b/src/Server/Coderr.Server.Api/Core/Users/NamespaceDoc.cs
new file mode 100644
index 00000000..475f4916
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Users/NamespaceDoc.cs
@@ -0,0 +1,20 @@
+using System.Runtime.CompilerServices;
+
+namespace Coderr.Server.Api.Core.Users
+{
+ // This file is Generated by the tool MarkdownToNamespaceDoc. ReadMe.md is the master.
+
+ ///
+ /// User related information (such as name, notifcation settings etc.)
+ ///
+ ///
+ ///
+ /// While accounts are for login authentication and authorization, users are for information about the
+ /// individual.
+ ///
+ ///
+ [CompilerGenerated]
+ internal class NamespaceDoc
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Users/NotificationSettings.cs b/src/Server/Coderr.Server.Api/Core/Users/NotificationSettings.cs
new file mode 100644
index 00000000..757c318d
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Users/NotificationSettings.cs
@@ -0,0 +1,40 @@
+using Coderr.Server.Api.Core.Users.Queries;
+
+namespace Coderr.Server.Api.Core.Users
+{
+ ///
+ /// Notification settings for .
+ ///
+ public class NotificationSettings
+ {
+ ///
+ /// How to notify when an incident is updated to critical.
+ ///
+ public NotificationState NotifyOnCriticalIncidents { get; set; }
+
+ ///
+ /// How to notify when an incident is updated to important.
+ ///
+ public NotificationState NotifyOnImportantIncidents { get; set; }
+
+ ///
+ /// How to notify when a new incident is created (received an unique exception)
+ ///
+ public NotificationState NotifyOnNewIncidents { get; set; }
+
+ ///
+ /// How to notify user when a peak is detected
+ ///
+ public NotificationState NotifyOnPeaks { get; set; }
+
+ ///
+ /// How to notify when we receive a new report on a closed incident.
+ ///
+ public NotificationState NotifyOnReOpenedIncident { get; set; }
+
+ ///
+ /// How to notify when an user have written an error description
+ ///
+ public NotificationState NotifyOnUserFeedback { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Users/NotificationState.cs b/src/Server/Coderr.Server.Api/Core/Users/NotificationState.cs
new file mode 100644
index 00000000..191af889
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Users/NotificationState.cs
@@ -0,0 +1,33 @@
+namespace Coderr.Server.Api.Core.Users
+{
+ ///
+ /// Type of notification to use
+ ///
+ public enum NotificationState
+ {
+ ///
+ /// Use global setting
+ ///
+ UseGlobalSetting = 1,
+
+ ///
+ /// Do not notify
+ ///
+ Disabled = 2,
+
+ ///
+ /// By cellphone (text message)
+ ///
+ Cellphone = 3,
+
+ ///
+ /// By email
+ ///
+ Email = 4,
+
+ ///
+ /// Use browser/desktop notifications.
+ ///
+ BrowserNotification = 5
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Users/Queries/GetUserSettings.cs b/src/Server/Coderr.Server.Api/Core/Users/Queries/GetUserSettings.cs
similarity index 87%
rename from src/Server/OneTrueError.Api/Core/Users/Queries/GetUserSettings.cs
rename to src/Server/Coderr.Server.Api/Core/Users/Queries/GetUserSettings.cs
index e365bedb..4f793040 100644
--- a/src/Server/OneTrueError.Api/Core/Users/Queries/GetUserSettings.cs
+++ b/src/Server/Coderr.Server.Api/Core/Users/Queries/GetUserSettings.cs
@@ -1,22 +1,23 @@
-using DotNetCqs;
-
-namespace OneTrueError.Api.Core.Users.Queries
-{
- ///
- /// Get settings for an user.
- ///
- public class GetUserSettings : Query
- {
- ///
- /// Get user settings for this application only
- ///
- public int ApplicationId { get; set; }
-
-
- ///
- /// User to get settings for
- ///
- [IgnoreField]
- public int UserId { get; set; }
- }
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Core.Users.Queries
+{
+ ///
+ /// Get settings for an user.
+ ///
+ [Message]
+ public class GetUserSettings : Query
+ {
+ ///
+ /// Get user settings for this application only
+ ///
+ public int ApplicationId { get; set; }
+
+
+ ///
+ /// User to get settings for
+ ///
+ [IgnoreField]
+ public int UserId { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Core/Users/Queries/GetUserSettingsResult.cs b/src/Server/Coderr.Server.Api/Core/Users/Queries/GetUserSettingsResult.cs
new file mode 100644
index 00000000..d7d40266
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Core/Users/Queries/GetUserSettingsResult.cs
@@ -0,0 +1,38 @@
+namespace Coderr.Server.Api.Core.Users.Queries
+{
+ ///
+ /// Result for
+ ///
+ ///
+ ///
+ /// All settings are system wide except for .
+ ///
+ ///
+ public class GetUserSettingsResult
+ {
+ ///
+ /// From the user account, always specified.
+ ///
+ public string EmailAddress { get; set; }
+
+ ///
+ /// First name (optional)
+ ///
+ public string FirstName { get; set; }
+
+ ///
+ /// Last name (optional)
+ ///
+ public string LastName { get; set; }
+
+ ///
+ /// Cell phone number (optional, but required for text notifications).
+ ///
+ public string MobileNumber { get; set; }
+
+ ///
+ /// Application specific settings
+ ///
+ public NotificationSettings Notifications { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Core/Users/ReadMe.md b/src/Server/Coderr.Server.Api/Core/Users/ReadMe.md
similarity index 100%
rename from src/Server/OneTrueError.Api/Core/Users/ReadMe.md
rename to src/Server/Coderr.Server.Api/Core/Users/ReadMe.md
diff --git a/src/Server/OneTrueError.Api/Core/EnumExtensions.cs b/src/Server/Coderr.Server.Api/EnumExtensions.cs
similarity index 95%
rename from src/Server/OneTrueError.Api/Core/EnumExtensions.cs
rename to src/Server/Coderr.Server.Api/EnumExtensions.cs
index 30b40ad7..1b39b308 100644
--- a/src/Server/OneTrueError.Api/Core/EnumExtensions.cs
+++ b/src/Server/Coderr.Server.Api/EnumExtensions.cs
@@ -1,37 +1,37 @@
-using System;
-
-namespace OneTrueError.Api.Core
-{
- ///
- /// Extensions making it easier to work with enums
- ///
- public static class EnumExtensions
- {
- ///
- /// Convert from one enum type to another
- ///
- /// Type to convert to
- /// source
- /// Converted enum value
- ///
- ///
- /// Does the conversion by translating the value to a string and then parsing it. That chocie was made
- /// since the same value might exist in both enums by representing different fields.
- ///
- ///
- /// Source enum value was not found in the target type.
- public static TTo ConvertEnum(this Enum source) where TTo : struct
- {
- var str = source.ToString();
- TTo result;
- if (!Enum.TryParse(str, true, out result))
- {
- throw new FormatException(
- string.Format("Cannot convert enum of type '{0}' with value '{1}' to enum type '{2}'.",
- source.GetType().FullName, source, typeof(TTo).FullName));
- }
-
- return result;
- }
- }
+using System;
+
+namespace Coderr.Server.Api
+{
+ ///
+ /// Extensions making it easier to work with enums
+ ///
+ public static class EnumExtensions
+ {
+ ///
+ /// Convert from one enum type to another
+ ///
+ /// Type to convert to
+ /// source
+ /// Converted enum value
+ ///
+ ///
+ /// Does the conversion by translating the value to a string and then parsing it. That chocie was made
+ /// since the same value might exist in both enums by representing different fields.
+ ///
+ ///
+ /// Source enum value was not found in the target type.
+ public static TTo ConvertEnum(this Enum source) where TTo : struct
+ {
+ var str = source.ToString();
+ TTo result;
+ if (!Enum.TryParse(str, true, out result))
+ {
+ throw new FormatException(
+ string.Format("Cannot convert enum of type '{0}' with value '{1}' to enum type '{2}'.",
+ source.GetType().FullName, source, typeof(TTo).FullName));
+ }
+
+ return result;
+ }
+ }
}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/EventAttribute.cs b/src/Server/Coderr.Server.Api/EventAttribute.cs
new file mode 100644
index 00000000..bb72ae6a
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/EventAttribute.cs
@@ -0,0 +1,10 @@
+namespace Coderr.Server.Api
+{
+ ///
+ /// Marks a DTO as an event.
+ ///
+ public class EventAttribute : MessageAttribute
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/IgnoreFieldAttribute.cs b/src/Server/Coderr.Server.Api/IgnoreFieldAttribute.cs
new file mode 100644
index 00000000..f517be69
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/IgnoreFieldAttribute.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace Coderr.Server.Api
+{
+ ///
+ /// Used to make the typescript compiler ignore certain properties and types.
+ ///
+ public class IgnoreFieldAttribute : Attribute
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/MessageAttribute.cs b/src/Server/Coderr.Server.Api/MessageAttribute.cs
new file mode 100644
index 00000000..2affc1d6
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/MessageAttribute.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace Coderr.Server.Api
+{
+ ///
+ /// Used to mark classes as DTOs (to be able to index and process them)
+ ///
+ public class MessageAttribute : Attribute
+ {
+ }
+}
diff --git a/src/Server/OneTrueError.Api/Modules/ContextData/Queries/GetSimilarities.cs b/src/Server/Coderr.Server.Api/Modules/ContextData/Queries/GetSimilarities.cs
similarity index 88%
rename from src/Server/OneTrueError.Api/Modules/ContextData/Queries/GetSimilarities.cs
rename to src/Server/Coderr.Server.Api/Modules/ContextData/Queries/GetSimilarities.cs
index 03caed99..10797cd4 100644
--- a/src/Server/OneTrueError.Api/Modules/ContextData/Queries/GetSimilarities.cs
+++ b/src/Server/Coderr.Server.Api/Modules/ContextData/Queries/GetSimilarities.cs
@@ -1,35 +1,36 @@
-using System;
-using DotNetCqs;
-
-namespace OneTrueError.Api.Modules.ContextData.Queries
-{
- ///
- /// Get similarities (i.e. analyzed context collections where we have normalized values and checked which values are
- /// more frequently occuring).
- ///
- public class GetSimilarities : Query
- {
- ///
- /// Serialization constructor
- ///
- protected GetSimilarities()
- {
- }
-
- ///
- /// Creates a new instance of .
- ///
- /// incident to get similarities for
- /// incidentId
- public GetSimilarities(int incidentId)
- {
- if (incidentId <= 0) throw new ArgumentOutOfRangeException("incidentId");
- IncidentId = incidentId;
- }
-
- ///
- /// incident to get similarities for
- ///
- public int IncidentId { get; private set; }
- }
+using System;
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Modules.ContextData.Queries
+{
+ ///
+ /// Get similarities (i.e. analyzed context collections where we have normalized values and checked which values are
+ /// more frequently occurring).
+ ///
+ [Message]
+ public class GetSimilarities : Query
+ {
+ ///
+ /// Serialization constructor
+ ///
+ protected GetSimilarities()
+ {
+ }
+
+ ///
+ /// Creates a new instance of .
+ ///
+ /// incident to get similarities for
+ /// incidentId
+ public GetSimilarities(int incidentId)
+ {
+ if (incidentId <= 0) throw new ArgumentOutOfRangeException("incidentId");
+ IncidentId = incidentId;
+ }
+
+ ///
+ /// incident to get similarities for
+ ///
+ public int IncidentId { get; private set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Modules/ContextData/Queries/GetSimilaritiesCollection.cs b/src/Server/Coderr.Server.Api/Modules/ContextData/Queries/GetSimilaritiesCollection.cs
similarity index 92%
rename from src/Server/OneTrueError.Api/Modules/ContextData/Queries/GetSimilaritiesCollection.cs
rename to src/Server/Coderr.Server.Api/Modules/ContextData/Queries/GetSimilaritiesCollection.cs
index 357dd92a..56010ba6 100644
--- a/src/Server/OneTrueError.Api/Modules/ContextData/Queries/GetSimilaritiesCollection.cs
+++ b/src/Server/Coderr.Server.Api/Modules/ContextData/Queries/GetSimilaritiesCollection.cs
@@ -1,38 +1,38 @@
-using System;
-using System.Collections.Generic;
-
-namespace OneTrueError.Api.Modules.ContextData.Queries
-{
- ///
- /// Context collection for .
- ///
- public class GetSimilaritiesCollection
- {
- private List _similarities = new List();
-
- ///
- /// Name of this collection.
- ///
- public string Name { get; set; }
-
- ///
- /// An analyzed property and all its values.
- ///
- public GetSimilaritiesSimilarity[] Similarities
- {
- get { return _similarities.ToArray(); }
- set { _similarities = new List(value); }
- }
-
- ///
- /// Add an analyzed property.
- ///
- /// property + values
- /// similarity
- public void Add(GetSimilaritiesSimilarity similarity)
- {
- if (similarity == null) throw new ArgumentNullException("similarity");
- _similarities.Add(similarity);
- }
- }
+using System;
+using System.Collections.Generic;
+
+namespace Coderr.Server.Api.Modules.ContextData.Queries
+{
+ ///
+ /// Context collection for .
+ ///
+ public class GetSimilaritiesCollection
+ {
+ private List _similarities = new List();
+
+ ///
+ /// Name of this collection.
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// An analyzed property and all its values.
+ ///
+ public GetSimilaritiesSimilarity[] Similarities
+ {
+ get { return _similarities.ToArray(); }
+ set { _similarities = new List(value); }
+ }
+
+ ///
+ /// Add an analyzed property.
+ ///
+ /// property + values
+ /// similarity
+ public void Add(GetSimilaritiesSimilarity similarity)
+ {
+ if (similarity == null) throw new ArgumentNullException("similarity");
+ _similarities.Add(similarity);
+ }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Modules/ContextData/Queries/GetSimilaritiesResult.cs b/src/Server/Coderr.Server.Api/Modules/ContextData/Queries/GetSimilaritiesResult.cs
similarity index 81%
rename from src/Server/OneTrueError.Api/Modules/ContextData/Queries/GetSimilaritiesResult.cs
rename to src/Server/Coderr.Server.Api/Modules/ContextData/Queries/GetSimilaritiesResult.cs
index 2785186e..aa2fd331 100644
--- a/src/Server/OneTrueError.Api/Modules/ContextData/Queries/GetSimilaritiesResult.cs
+++ b/src/Server/Coderr.Server.Api/Modules/ContextData/Queries/GetSimilaritiesResult.cs
@@ -1,13 +1,13 @@
-namespace OneTrueError.Api.Modules.ContextData.Queries
-{
- ///
- /// Result for .
- ///
- public class GetSimilaritiesResult
- {
- ///
- /// All analyzed context collections
- ///
- public GetSimilaritiesCollection[] Collections { get; set; }
- }
+namespace Coderr.Server.Api.Modules.ContextData.Queries
+{
+ ///
+ /// Result for .
+ ///
+ public class GetSimilaritiesResult
+ {
+ ///
+ /// All analyzed context collections
+ ///
+ public GetSimilaritiesCollection[] Collections { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Modules/ContextData/Queries/GetSimilaritiesSimilarity.cs b/src/Server/Coderr.Server.Api/Modules/ContextData/Queries/GetSimilaritiesSimilarity.cs
similarity index 92%
rename from src/Server/OneTrueError.Api/Modules/ContextData/Queries/GetSimilaritiesSimilarity.cs
rename to src/Server/Coderr.Server.Api/Modules/ContextData/Queries/GetSimilaritiesSimilarity.cs
index 5e442294..81e487af 100644
--- a/src/Server/OneTrueError.Api/Modules/ContextData/Queries/GetSimilaritiesSimilarity.cs
+++ b/src/Server/Coderr.Server.Api/Modules/ContextData/Queries/GetSimilaritiesSimilarity.cs
@@ -1,41 +1,41 @@
-using System;
-
-namespace OneTrueError.Api.Modules.ContextData.Queries
-{
- ///
- /// A property in .
- ///
- public class GetSimilaritiesSimilarity
- {
- ///
- /// Creates a new instance of .
- ///
- /// Property name
- /// name
- public GetSimilaritiesSimilarity(string name)
- {
- if (name == null) throw new ArgumentNullException("name");
- Name = name;
- Values = new GetSimilaritiesValue[0];
- }
-
- ///
- /// Serialization constructor.
- ///
- protected GetSimilaritiesSimilarity()
- {
- Values = new GetSimilaritiesValue[0];
- }
-
- ///
- /// Name of this similarity.
- ///
- public string Name { get; private set; }
-
-
- ///
- /// The different values that this one have got.
- ///
- public GetSimilaritiesValue[] Values { get; set; }
- }
+using System;
+
+namespace Coderr.Server.Api.Modules.ContextData.Queries
+{
+ ///
+ /// A property in .
+ ///
+ public class GetSimilaritiesSimilarity
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// Property name
+ /// name
+ public GetSimilaritiesSimilarity(string name)
+ {
+ if (name == null) throw new ArgumentNullException("name");
+ Name = name;
+ Values = new GetSimilaritiesValue[0];
+ }
+
+ ///
+ /// Serialization constructor.
+ ///
+ protected GetSimilaritiesSimilarity()
+ {
+ Values = new GetSimilaritiesValue[0];
+ }
+
+ ///
+ /// Name of this similarity.
+ ///
+ public string Name { get; private set; }
+
+
+ ///
+ /// The different values that this one have got.
+ ///
+ public GetSimilaritiesValue[] Values { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Modules/ContextData/Queries/GetSimilaritiesValue.cs b/src/Server/Coderr.Server.Api/Modules/ContextData/Queries/GetSimilaritiesValue.cs
similarity index 93%
rename from src/Server/OneTrueError.Api/Modules/ContextData/Queries/GetSimilaritiesValue.cs
rename to src/Server/Coderr.Server.Api/Modules/ContextData/Queries/GetSimilaritiesValue.cs
index a437c89e..462a3502 100644
--- a/src/Server/OneTrueError.Api/Modules/ContextData/Queries/GetSimilaritiesValue.cs
+++ b/src/Server/Coderr.Server.Api/Modules/ContextData/Queries/GetSimilaritiesValue.cs
@@ -1,44 +1,44 @@
-using System;
-
-namespace OneTrueError.Api.Modules.ContextData.Queries
-{
- ///
- /// A single value for .
- ///
- public class GetSimilaritiesValue
- {
- ///
- /// Creates a new instance of .
- ///
- /// Value, null is allowed
- /// 0-100
- /// Number of times that this value have been received.
- ///
- public GetSimilaritiesValue(string value, int percentage, int count)
- {
- if (percentage < 0 || percentage > 100)
- throw new ArgumentOutOfRangeException("percentage", percentage,
- "Percentage should be between 0 and 100.");
- if (count <= 0) throw new ArgumentOutOfRangeException("count");
-
- Value = value;
- Percentage = percentage;
- Count = count;
- }
-
- ///
- /// Number of times that this value have been found in an error report.
- ///
- public int Count { get; set; }
-
- ///
- /// 0-100
- ///
- public int Percentage { get; set; }
-
- ///
- /// Value for this item
- ///
- public string Value { get; set; }
- }
+using System;
+
+namespace Coderr.Server.Api.Modules.ContextData.Queries
+{
+ ///
+ /// A single value for .
+ ///
+ public class GetSimilaritiesValue
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// Value, null is allowed
+ /// 0-100
+ /// Number of times that this value have been received.
+ ///
+ public GetSimilaritiesValue(string value, int percentage, int count)
+ {
+ if (percentage < 0 || percentage > 100)
+ throw new ArgumentOutOfRangeException("percentage", percentage,
+ "Percentage should be between 0 and 100.");
+ if (count <= 0) throw new ArgumentOutOfRangeException("count");
+
+ Value = value;
+ Percentage = percentage;
+ Count = count;
+ }
+
+ ///
+ /// Number of times that this value have been found in an error report.
+ ///
+ public int Count { get; set; }
+
+ ///
+ /// 0-100
+ ///
+ public int Percentage { get; set; }
+
+ ///
+ /// Value for this item
+ ///
+ public string Value { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Modules/ErrorOrigins/Queries/GetOriginsForIncident.cs b/src/Server/Coderr.Server.Api/Modules/ErrorOrigins/Queries/GetOriginsForIncident.cs
similarity index 91%
rename from src/Server/OneTrueError.Api/Modules/ErrorOrigins/Queries/GetOriginsForIncident.cs
rename to src/Server/Coderr.Server.Api/Modules/ErrorOrigins/Queries/GetOriginsForIncident.cs
index e321f584..6af85cd6 100644
--- a/src/Server/OneTrueError.Api/Modules/ErrorOrigins/Queries/GetOriginsForIncident.cs
+++ b/src/Server/Coderr.Server.Api/Modules/ErrorOrigins/Queries/GetOriginsForIncident.cs
@@ -1,34 +1,35 @@
-using System;
-using DotNetCqs;
-
-namespace OneTrueError.Api.Modules.ErrorOrigins.Queries
-{
- ///
- /// Get all error origins for the specified incident.
- ///
- public class GetOriginsForIncident : Query
- {
- ///
- /// Creates a new instance of .
- ///
- /// incident to get error origins for
- /// incidentId < 1
- public GetOriginsForIncident(int incidentId)
- {
- if (incidentId <= 0) throw new ArgumentOutOfRangeException("incidentId");
- IncidentId = incidentId;
- }
-
- ///
- /// Serialization constructor
- ///
- protected GetOriginsForIncident()
- {
- }
-
- ///
- /// Incident to get origins for
- ///
- public int IncidentId { get; private set; }
- }
+using System;
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Modules.ErrorOrigins.Queries
+{
+ ///
+ /// Get all error origins for the specified incident.
+ ///
+ [Message]
+ public class GetOriginsForIncident : Query
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// incident to get error origins for
+ /// incidentId < 1
+ public GetOriginsForIncident(int incidentId)
+ {
+ if (incidentId <= 0) throw new ArgumentOutOfRangeException("incidentId");
+ IncidentId = incidentId;
+ }
+
+ ///
+ /// Serialization constructor
+ ///
+ protected GetOriginsForIncident()
+ {
+ }
+
+ ///
+ /// Incident to get origins for
+ ///
+ public int IncidentId { get; private set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Modules/ErrorOrigins/Queries/GetOriginsForIncidentResult.cs b/src/Server/Coderr.Server.Api/Modules/ErrorOrigins/Queries/GetOriginsForIncidentResult.cs
similarity index 81%
rename from src/Server/OneTrueError.Api/Modules/ErrorOrigins/Queries/GetOriginsForIncidentResult.cs
rename to src/Server/Coderr.Server.Api/Modules/ErrorOrigins/Queries/GetOriginsForIncidentResult.cs
index 427d7e8e..18ab387b 100644
--- a/src/Server/OneTrueError.Api/Modules/ErrorOrigins/Queries/GetOriginsForIncidentResult.cs
+++ b/src/Server/Coderr.Server.Api/Modules/ErrorOrigins/Queries/GetOriginsForIncidentResult.cs
@@ -1,13 +1,13 @@
-namespace OneTrueError.Api.Modules.ErrorOrigins.Queries
-{
- ///
- /// Result for .
- ///
- public class GetOriginsForIncidentResult
- {
- ///
- /// One item per geographic location
- ///
- public GetOriginsForIncidentResultItem[] Items { get; set; }
- }
+namespace Coderr.Server.Api.Modules.ErrorOrigins.Queries
+{
+ ///
+ /// Result for .
+ ///
+ public class GetOriginsForIncidentResult
+ {
+ ///
+ /// One item per geographic location
+ ///
+ public GetOriginsForIncidentResultItem[] Items { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Modules/ErrorOrigins/Queries/GetOriginsForIncidentResultItem.cs b/src/Server/Coderr.Server.Api/Modules/ErrorOrigins/Queries/GetOriginsForIncidentResultItem.cs
similarity index 87%
rename from src/Server/OneTrueError.Api/Modules/ErrorOrigins/Queries/GetOriginsForIncidentResultItem.cs
rename to src/Server/Coderr.Server.Api/Modules/ErrorOrigins/Queries/GetOriginsForIncidentResultItem.cs
index b6bc276b..f8e4bb21 100644
--- a/src/Server/OneTrueError.Api/Modules/ErrorOrigins/Queries/GetOriginsForIncidentResultItem.cs
+++ b/src/Server/Coderr.Server.Api/Modules/ErrorOrigins/Queries/GetOriginsForIncidentResultItem.cs
@@ -1,23 +1,23 @@
-namespace OneTrueError.Api.Modules.ErrorOrigins.Queries
-{
- ///
- /// Item for .
- ///
- public class GetOriginsForIncidentResultItem
- {
- ///
- /// Latitude
- ///
- public double Latitude { get; set; }
-
- ///
- /// Longitude
- ///
- public double Longitude { get; set; }
-
- ///
- /// Number of error reports that have been received from this incident
- ///
- public int NumberOfErrorReports { get; set; }
- }
+namespace Coderr.Server.Api.Modules.ErrorOrigins.Queries
+{
+ ///
+ /// Item for .
+ ///
+ public class GetOriginsForIncidentResultItem
+ {
+ ///
+ /// Latitude
+ ///
+ public double Latitude { get; set; }
+
+ ///
+ /// Longitude
+ ///
+ public double Longitude { get; set; }
+
+ ///
+ /// Number of error reports that have been received from this incident
+ ///
+ public int NumberOfErrorReports { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Modules/History/Queries/GetIncidentStateSummary.cs b/src/Server/Coderr.Server.Api/Modules/History/Queries/GetIncidentStateSummary.cs
new file mode 100644
index 00000000..32263751
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Modules/History/Queries/GetIncidentStateSummary.cs
@@ -0,0 +1,9 @@
+namespace Coderr.Server.Api.Modules.History.Queries
+{
+ [Message]
+ public class GetIncidentStateSummary
+ {
+ public int ApplicationId { get; set; }
+ public string ApplicationVersion { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Modules/History/Queries/GetIncidentStateSummaryResult.cs b/src/Server/Coderr.Server.Api/Modules/History/Queries/GetIncidentStateSummaryResult.cs
new file mode 100644
index 00000000..da81a0f7
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Modules/History/Queries/GetIncidentStateSummaryResult.cs
@@ -0,0 +1,9 @@
+namespace Coderr.Server.Api.Modules.History.Queries
+{
+ public class GetIncidentStateSummaryResult
+ {
+ public int ClosedCount { get; set; }
+ public int NewCount { get; set; }
+ public int ReOpenedCount { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Modules/History/Queries/GetIncidentsForState.cs b/src/Server/Coderr.Server.Api/Modules/History/Queries/GetIncidentsForState.cs
new file mode 100644
index 00000000..6e317a08
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Modules/History/Queries/GetIncidentsForState.cs
@@ -0,0 +1,18 @@
+using System.Collections.Generic;
+using System.Text;
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Modules.History.Queries
+{
+ [Message]
+ public class GetIncidentsForStates : Query
+ {
+ public string ApplicationVersion { get; set; }
+ public int ApplicationId { get; set; }
+
+ public bool IsClosed { get; set; }
+ public bool IsNew { get; set; }
+
+ public bool IsReopened { get; set; }
+ }
+}
diff --git a/src/Server/Coderr.Server.Api/Modules/History/Queries/GetIncidentsForStatesResult.cs b/src/Server/Coderr.Server.Api/Modules/History/Queries/GetIncidentsForStatesResult.cs
new file mode 100644
index 00000000..04b0b705
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Modules/History/Queries/GetIncidentsForStatesResult.cs
@@ -0,0 +1,7 @@
+namespace Coderr.Server.Api.Modules.History.Queries
+{
+ public class GetIncidentsForStatesResult
+ {
+ public GetIncidentsForStatesResultItem[] Items { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Modules/History/Queries/GetIncidentsForStatesResultItem.cs b/src/Server/Coderr.Server.Api/Modules/History/Queries/GetIncidentsForStatesResultItem.cs
new file mode 100644
index 00000000..ded7afcc
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Modules/History/Queries/GetIncidentsForStatesResultItem.cs
@@ -0,0 +1,16 @@
+using System;
+
+namespace Coderr.Server.Api.Modules.History.Queries
+{
+ public class GetIncidentsForStatesResultItem
+ {
+ public int IncidentId { get; set; }
+ public string IncidentName { get; set; }
+ public DateTime CreatedAtUtc { get; set; }
+
+ public bool IsClosed { get; set; }
+ public bool IsNew { get; set; }
+
+ public bool IsReopened { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Modules/Logs/Queries/GetLogs.cs b/src/Server/Coderr.Server.Api/Modules/Logs/Queries/GetLogs.cs
new file mode 100644
index 00000000..0687ef1f
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Modules/Logs/Queries/GetLogs.cs
@@ -0,0 +1,38 @@
+using System;
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Modules.Logs.Queries
+{
+ [Message]
+ public class GetLogs : Query
+ {
+ public GetLogs(int incidentId)
+ {
+ if (incidentId <= 0) throw new ArgumentOutOfRangeException(nameof(incidentId));
+ IncidentId = incidentId;
+ }
+
+ public GetLogs(int incidentId, int reportId)
+ {
+ if (incidentId <= 0) throw new ArgumentOutOfRangeException(nameof(incidentId));
+ if (reportId <= 0) throw new ArgumentOutOfRangeException(nameof(reportId));
+ IncidentId = incidentId;
+ ReportId = reportId;
+ }
+
+ protected GetLogs()
+ {
+
+ }
+
+ ///
+ /// Incident to check.
+ ///
+ public int IncidentId { get; private set; }
+
+ ///
+ /// Check for a specific report (if set).
+ ///
+ public int? ReportId { get; private set; }
+ }
+}
diff --git a/src/Server/Coderr.Server.Api/Modules/Logs/Queries/GetLogsResult.cs b/src/Server/Coderr.Server.Api/Modules/Logs/Queries/GetLogsResult.cs
new file mode 100644
index 00000000..fa220056
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Modules/Logs/Queries/GetLogsResult.cs
@@ -0,0 +1,7 @@
+namespace Coderr.Server.Api.Modules.Logs.Queries
+{
+ public class GetLogsResult
+ {
+ public GetLogsResultEntry[] Entries { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Modules/Logs/Queries/GetLogsResultEntry.cs b/src/Server/Coderr.Server.Api/Modules/Logs/Queries/GetLogsResultEntry.cs
new file mode 100644
index 00000000..a8a6bd9a
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Modules/Logs/Queries/GetLogsResultEntry.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Coderr.Server.Api.Modules.Logs.Queries
+{
+ public class GetLogsResultEntry
+ {
+ public DateTime TimeStampUtc { get; set; }
+
+ public string Message { get; set; }
+
+ public GetLogsResultEntryLevel Level { get; set; }
+
+ public string Exception { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Modules/Logs/Queries/GetLogsResultEntryLevel.cs b/src/Server/Coderr.Server.Api/Modules/Logs/Queries/GetLogsResultEntryLevel.cs
new file mode 100644
index 00000000..99c6be59
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Modules/Logs/Queries/GetLogsResultEntryLevel.cs
@@ -0,0 +1,12 @@
+namespace Coderr.Server.Api.Modules.Logs.Queries
+{
+ public enum GetLogsResultEntryLevel
+ {
+ Trace = 1,
+ Debug = 2,
+ Info = 3,
+ Warning = 4,
+ Error = 5,
+ Critical = 6
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Modules/Logs/Queries/HasLogs.cs b/src/Server/Coderr.Server.Api/Modules/Logs/Queries/HasLogs.cs
new file mode 100644
index 00000000..2615de86
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Modules/Logs/Queries/HasLogs.cs
@@ -0,0 +1,41 @@
+using System;
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Modules.Logs.Queries
+{
+ ///
+ /// Check if an incident (or a specific report for that incident) has logs attached to it.
+ ///
+ [Message]
+ public class HasLogs : Query
+ {
+ public HasLogs(int incidentId)
+ {
+ if (incidentId <= 0) throw new ArgumentOutOfRangeException(nameof(incidentId));
+ IncidentId = incidentId;
+ }
+
+ public HasLogs(int incidentId, int reportId)
+ {
+ if (incidentId <= 0) throw new ArgumentOutOfRangeException(nameof(incidentId));
+ if (reportId <= 0) throw new ArgumentOutOfRangeException(nameof(reportId));
+ IncidentId = incidentId;
+ ReportId = reportId;
+ }
+
+ protected HasLogs()
+ {
+
+ }
+
+ ///
+ /// Incident to check.
+ ///
+ public int IncidentId { get; private set; }
+
+ ///
+ /// Check for a specific report (if set).
+ ///
+ public int? ReportId { get; private set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Modules/Logs/Queries/HasLogsReply.cs b/src/Server/Coderr.Server.Api/Modules/Logs/Queries/HasLogsReply.cs
new file mode 100644
index 00000000..5401dc4f
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Modules/Logs/Queries/HasLogsReply.cs
@@ -0,0 +1,7 @@
+namespace Coderr.Server.Api.Modules.Logs.Queries
+{
+ public class HasLogsReply
+ {
+ public bool HasLogs { get; set; }
+ }
+}
diff --git a/src/Server/Coderr.Server.Api/Modules/Mine/Queries/ListMyIncidents.cs b/src/Server/Coderr.Server.Api/Modules/Mine/Queries/ListMyIncidents.cs
new file mode 100644
index 00000000..bfc8df3f
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Modules/Mine/Queries/ListMyIncidents.cs
@@ -0,0 +1,16 @@
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Modules.Mine.Queries
+{
+ ///
+ /// Get the users assigned incidents and the ones that are recommended for that person.
+ ///
+ [Message]
+ public class ListMyIncidents : Query
+ {
+ ///
+ /// Limit to the given application (if specified).
+ ///
+ public int? ApplicationId { get; set; }
+ }
+}
diff --git a/src/Server/Coderr.Server.Api/Modules/Mine/Queries/ListMyIncidentsResult.cs b/src/Server/Coderr.Server.Api/Modules/Mine/Queries/ListMyIncidentsResult.cs
new file mode 100644
index 00000000..54dc1271
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Modules/Mine/Queries/ListMyIncidentsResult.cs
@@ -0,0 +1,14 @@
+using System.Collections.Generic;
+
+namespace Coderr.Server.Api.Modules.Mine.Queries
+{
+ ///
+ /// Result for .
+ ///
+ public class ListMyIncidentsResult
+ {
+ public string Comment { get; set; }
+ public IList Items { get; set; }
+ public IList Suggestions { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Modules/Mine/Queries/ListMyIncidentsResultItem.cs b/src/Server/Coderr.Server.Api/Modules/Mine/Queries/ListMyIncidentsResultItem.cs
new file mode 100644
index 00000000..d7d09106
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Modules/Mine/Queries/ListMyIncidentsResultItem.cs
@@ -0,0 +1,72 @@
+using System;
+
+namespace Coderr.Server.Api.Modules.Mine.Queries
+{
+ ///
+ /// Item for .
+ ///
+ public class ListMyIncidentsResultItem
+ {
+ ///
+ /// Creates new instance of .
+ ///
+ /// incident id
+ /// incident name
+ public ListMyIncidentsResultItem(int id, string name)
+ {
+ if (name == null) throw new ArgumentNullException("name");
+ if (id <= 0) throw new ArgumentOutOfRangeException("id");
+ Id = id;
+ Name = name;
+ }
+
+ ///
+ /// Serialization constructor
+ ///
+ protected ListMyIncidentsResultItem()
+ {
+ }
+
+ ///
+ /// Id of the application that this incident belongs to
+ ///
+ public int ApplicationId { get; set; }
+
+ ///
+ /// Name of the application that this incident belongs to
+ ///
+ public string ApplicationName { get; set; }
+
+ ///
+ /// when this incident was assigned to me.
+ ///
+ public DateTime AssignedAtUtc { get; set; }
+
+ ///
+ /// When the first report was received.
+ ///
+ public DateTime CreatedAtUtc { get; set; }
+
+ public int DaysOld => (int)DateTime.UtcNow.Subtract(CreatedAtUtc).TotalDays;
+
+ ///
+ /// Incident id
+ ///
+ public int Id { get; private set; }
+
+ ///
+ /// When the last report was received (or when the last user action was made)
+ ///
+ public DateTime LastReportAtUtc { get; set; }
+
+ ///
+ /// Incident name
+ ///
+ public string Name { get; private set; }
+
+ ///
+ /// Total number of received reports (increased even if the number of stored reports are at the limit)
+ ///
+ public int ReportCount { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Modules/Mine/Queries/ListMySuggestedItem.cs b/src/Server/Coderr.Server.Api/Modules/Mine/Queries/ListMySuggestedItem.cs
new file mode 100644
index 00000000..52bde240
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Modules/Mine/Queries/ListMySuggestedItem.cs
@@ -0,0 +1,79 @@
+using System;
+
+namespace Coderr.Server.Api.Modules.Mine.Queries
+{
+ ///
+ /// Item for .
+ ///
+ public class ListMySuggestedItem
+ {
+ ///
+ /// Creates new instance of .
+ ///
+ /// incident id
+ /// incident name
+ public ListMySuggestedItem(int id, string name)
+ {
+ if (name == null) throw new ArgumentNullException("name");
+ if (id <= 0) throw new ArgumentOutOfRangeException("id");
+ Id = id;
+ Name = name;
+ }
+
+ ///
+ /// Serialization constructor
+ ///
+ protected ListMySuggestedItem()
+ {
+ }
+
+ ///
+ /// Id of the application that this incident belongs to
+ ///
+ public int ApplicationId { get; set; }
+
+ ///
+ /// Name of the application that this incident belongs to
+ ///
+ public string ApplicationName { get; set; }
+
+ ///
+ /// When the first report was received.
+ ///
+ public DateTime CreatedAtUtc { get; set; }
+
+ public string ExceptionTypeName { get; set; }
+
+ ///
+ /// Incident id
+ ///
+ public int Id { get; private set; }
+
+ ///
+ /// When the last report was received (or when the last user action was made)
+ ///
+ public DateTime LastReportAtUtc { get; set; }
+
+ ///
+ /// Incident name
+ ///
+ public string Name { get; private set; }
+
+ ///
+ /// Number of points for this item. the more the merrier.
+ ///
+ public int Weight { get; set; }
+
+ ///
+ /// Total number of received reports (increased even if the number of stored reports are at the limit)
+ ///
+ public int ReportCount { get; set; }
+
+ public string StackTrace { get; set; }
+
+ ///
+ /// Why this item was suggested.
+ ///
+ public string Motivation { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Modules/Onboarding/Commands/SetOnboardingChoices.cs b/src/Server/Coderr.Server.Api/Modules/Onboarding/Commands/SetOnboardingChoices.cs
new file mode 100644
index 00000000..1ea3c787
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Modules/Onboarding/Commands/SetOnboardingChoices.cs
@@ -0,0 +1,23 @@
+using System.Collections.Generic;
+
+namespace Coderr.Server.Api.Modules.Onboarding.Commands
+{
+ ///
+ /// Set current state of the onboarding.
+ ///
+ [Command]
+ public class SetOnboardingChoices
+ {
+ ///
+ /// All libraries that the user wants to generate example incidents for.
+ ///
+ public IReadOnlyList Libraries { get; set; }
+
+ ///
+ /// DOTNET or NODEJS
+ ///
+ public string MainLanguage { get; set; }
+
+ public string Feedback { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Modules/Onboarding/Queries/GetOnboardingState.cs b/src/Server/Coderr.Server.Api/Modules/Onboarding/Queries/GetOnboardingState.cs
new file mode 100644
index 00000000..6845116d
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Modules/Onboarding/Queries/GetOnboardingState.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Text;
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Modules.Onboarding.Queries
+{
+
+ ///
+ /// Get current state of the onboarding process.
+ ///
+ /// The onboarding process is only run for the admin, and therefore these settings are site wide.
+ [Message]
+ public class GetOnboardingState : Query
+ {
+
+ }
+}
diff --git a/src/Server/Coderr.Server.Api/Modules/Onboarding/Queries/GetOnboardingStateResult.cs b/src/Server/Coderr.Server.Api/Modules/Onboarding/Queries/GetOnboardingStateResult.cs
new file mode 100644
index 00000000..c4a9257a
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Modules/Onboarding/Queries/GetOnboardingStateResult.cs
@@ -0,0 +1,26 @@
+using System.Collections.Generic;
+
+namespace Coderr.Server.Api.Modules.Onboarding.Queries
+{
+ ///
+ /// Result for
+ ///
+ public class GetOnboardingStateResult
+ {
+ ///
+ /// Onboarding is completed.
+ ///
+ public bool IsComplete { get; set; }
+
+ ///
+ /// Libraries that the user generated demo incidents for.
+ ///
+ public IReadOnlyList Libraries { get; set; }
+
+ ///
+ /// DOTNET or NODEJS
+ ///
+ public string MainLanguage { get; set; }
+
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Modules/Tagging/Events/TagAttachedToIncident.cs b/src/Server/Coderr.Server.Api/Modules/Tagging/Events/TagAttachedToIncident.cs
new file mode 100644
index 00000000..978d93cf
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Modules/Tagging/Events/TagAttachedToIncident.cs
@@ -0,0 +1,45 @@
+using System;
+
+namespace Coderr.Server.Api.Modules.Tagging.Events
+{
+ ///
+ /// New tag(s) have been identified for the processed incident.
+ ///
+ [Message]
+ public class TagAttachedToIncident
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// Incident being processed
+ /// tags
+ /// tags
+ /// incidentId
+ public TagAttachedToIncident(int applicationId, int incidentId, string[] tags)
+ {
+ if (tags == null) throw new ArgumentNullException("tags");
+ if (incidentId <= 0) throw new ArgumentOutOfRangeException("incidentId");
+ if (applicationId <= 0) throw new ArgumentOutOfRangeException(nameof(applicationId));
+ ApplicationId = applicationId;
+ Tags = tags;
+ IncidentId = incidentId;
+ }
+
+ protected TagAttachedToIncident()
+ {
+
+ }
+
+ ///
+ /// Incident being processed
+ ///
+ public int IncidentId { get; private set; }
+
+ public int ApplicationId { get; private set; }
+
+ ///
+ /// Identified tags
+ ///
+ public string[] Tags { get; private set; }
+ }
+}
diff --git a/src/Server/Coderr.Server.Api/Modules/Tagging/Queries/GetTags.cs b/src/Server/Coderr.Server.Api/Modules/Tagging/Queries/GetTags.cs
new file mode 100644
index 00000000..523002fe
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Modules/Tagging/Queries/GetTags.cs
@@ -0,0 +1,21 @@
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Modules.Tagging.Queries
+{
+ ///
+ /// Get all tags that the system have identified for an incident.
+ ///
+ [Message]
+ public class GetTags : Query
+ {
+ ///
+ /// Application to get tags for
+ ///
+ public int? ApplicationId { get; set; }
+
+ ///
+ /// Incident to get tags for
+ ///
+ public int? IncidentId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Modules/Tagging/Queries/GetTagsForApplication.cs b/src/Server/Coderr.Server.Api/Modules/Tagging/Queries/GetTagsForApplication.cs
new file mode 100644
index 00000000..8189b414
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Modules/Tagging/Queries/GetTagsForApplication.cs
@@ -0,0 +1,28 @@
+using System;
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Modules.Tagging.Queries
+{
+ ///
+ /// Get all tags that the system have identified for an incident.
+ ///
+ [Message]
+ public class GetTagsForApplication : Query
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// Incident to get tags for
+ /// incidentId
+ public GetTagsForApplication(int applicationId)
+ {
+ if (applicationId <= 0) throw new ArgumentOutOfRangeException("applicationId");
+ ApplicationId = applicationId;
+ }
+
+ ///
+ /// Incident to get tags for
+ ///
+ public int ApplicationId { get; private set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Modules/Tagging/Queries/GetTagsForIncident.cs b/src/Server/Coderr.Server.Api/Modules/Tagging/Queries/GetTagsForIncident.cs
similarity index 91%
rename from src/Server/OneTrueError.Api/Modules/Tagging/Queries/GetTagsForIncident.cs
rename to src/Server/Coderr.Server.Api/Modules/Tagging/Queries/GetTagsForIncident.cs
index bb1e359f..7171dc42 100644
--- a/src/Server/OneTrueError.Api/Modules/Tagging/Queries/GetTagsForIncident.cs
+++ b/src/Server/Coderr.Server.Api/Modules/Tagging/Queries/GetTagsForIncident.cs
@@ -1,27 +1,28 @@
-using System;
-using DotNetCqs;
-
-namespace OneTrueError.Api.Modules.Tagging.Queries
-{
- ///
- /// Get all tags that the system have identified for an incident.
- ///
- public class GetTagsForIncident : Query
- {
- ///
- /// Creates a new instance of .
- ///
- /// Incident to get tags for
- /// incidentId
- public GetTagsForIncident(int incidentId)
- {
- if (incidentId <= 0) throw new ArgumentOutOfRangeException("incidentId");
- IncidentId = incidentId;
- }
-
- ///
- /// Incident to get tags for
- ///
- public int IncidentId { get; private set; }
- }
+using System;
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Modules.Tagging.Queries
+{
+ ///
+ /// Get all tags that the system have identified for an incident.
+ ///
+ [Message]
+ public class GetTagsForIncident : Query
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// Incident to get tags for
+ /// incidentId
+ public GetTagsForIncident(int incidentId)
+ {
+ if (incidentId <= 0) throw new ArgumentOutOfRangeException("incidentId");
+ IncidentId = incidentId;
+ }
+
+ ///
+ /// Incident to get tags for
+ ///
+ public int IncidentId { get; private set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Modules/Tagging/TagDTO.cs b/src/Server/Coderr.Server.Api/Modules/Tagging/TagDTO.cs
similarity index 85%
rename from src/Server/OneTrueError.Api/Modules/Tagging/TagDTO.cs
rename to src/Server/Coderr.Server.Api/Modules/Tagging/TagDTO.cs
index 3605f46a..7b34354d 100644
--- a/src/Server/OneTrueError.Api/Modules/Tagging/TagDTO.cs
+++ b/src/Server/Coderr.Server.Api/Modules/Tagging/TagDTO.cs
@@ -1,18 +1,18 @@
-namespace OneTrueError.Api.Modules.Tagging
-{
- ///
- /// A stack overflow tag
- ///
- public class TagDTO
- {
- ///
- /// Name
- ///
- public string Name { get; set; }
-
- ///
- /// Used to sort tags before displaying them.
- ///
- public int OrderNumber { get; set; }
- }
+namespace Coderr.Server.Api.Modules.Tagging
+{
+ ///
+ /// A stack overflow tag
+ ///
+ public class TagDTO
+ {
+ ///
+ /// Name
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// Used to sort tags before displaying them.
+ ///
+ public int OrderNumber { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Modules/Triggers/Commands/CreateTrigger.cs b/src/Server/Coderr.Server.Api/Modules/Triggers/Commands/CreateTrigger.cs
similarity index 92%
rename from src/Server/OneTrueError.Api/Modules/Triggers/Commands/CreateTrigger.cs
rename to src/Server/Coderr.Server.Api/Modules/Triggers/Commands/CreateTrigger.cs
index a5a3db74..55d35bdb 100644
--- a/src/Server/OneTrueError.Api/Modules/Triggers/Commands/CreateTrigger.cs
+++ b/src/Server/Coderr.Server.Api/Modules/Triggers/Commands/CreateTrigger.cs
@@ -1,83 +1,83 @@
-using System;
-using DotNetCqs;
-
-namespace OneTrueError.Api.Modules.Triggers.Commands
-{
- ///
- /// Create a new trigger
- ///
- public class CreateTrigger : Command
- {
- ///
- /// Creates a new instance of .
- ///
- /// Application that the trigger is for.
- /// Trigger name
- public CreateTrigger(int applicationId, string name)
- {
- if (name == null) throw new ArgumentNullException("name");
- if (applicationId <= 0) throw new ArgumentOutOfRangeException("applicationId");
-
- ApplicationId = applicationId;
- Name = name;
- }
-
- ///
- /// Serialization constructor
- ///
- protected CreateTrigger()
- {
- }
-
- ///
- /// Actions to run
- ///
- public TriggerActionDataDTO[] Actions { get; set; }
-
- ///
- /// Application that the trigger belongs to.
- ///
- public int ApplicationId { get; private set; }
-
- ///
- /// What the trigger does and why
- ///
- public string Description { get; set; }
-
- ///
- /// Primary key
- ///
- public int Id { get; set; }
-
- ///
- /// Action to take after all have run.
- ///
- public LastTriggerActionDTO LastTriggerAction { get; set; }
-
-
- ///
- /// Trigger name.
- ///
- public string Name { get; private set; }
-
- ///
- /// Rules that determine if this trigger can run.
- ///
- public TriggerRuleBase[] Rules { get; set; }
-
- ///
- /// Run trigger for existing incidents (received a duplicate exception)
- ///
- public bool RunForExistingIncidents { get; set; }
-
- ///
- /// Run trigger for new incidents (i.e. received a new unique exception)
- ///
- public bool RunForNewIncidents { get; set; }
-
- ///
- /// Run for incidents that is closed but received a new error report.
- ///
- public bool RunForReOpenedIncidents { get; set; }
- }
+using System;
+
+namespace Coderr.Server.Api.Modules.Triggers.Commands
+{
+ ///
+ /// Create a new trigger
+ ///
+ [Message]
+ public class CreateTrigger
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// Application that the trigger is for.
+ /// Trigger name
+ public CreateTrigger(int applicationId, string name)
+ {
+ if (name == null) throw new ArgumentNullException("name");
+ if (applicationId <= 0) throw new ArgumentOutOfRangeException("applicationId");
+
+ ApplicationId = applicationId;
+ Name = name;
+ }
+
+ ///
+ /// Serialization constructor
+ ///
+ protected CreateTrigger()
+ {
+ }
+
+ ///
+ /// Actions to run
+ ///
+ public TriggerActionDataDTO[] Actions { get; set; }
+
+ ///
+ /// Application that the trigger belongs to.
+ ///
+ public int ApplicationId { get; private set; }
+
+ ///
+ /// What the trigger does and why
+ ///
+ public string Description { get; set; }
+
+ ///
+ /// Primary key
+ ///
+ public int Id { get; set; }
+
+ ///
+ /// Action to take after all have run.
+ ///
+ public LastTriggerActionDTO LastTriggerAction { get; set; }
+
+
+ ///
+ /// Trigger name.
+ ///
+ public string Name { get; private set; }
+
+ ///
+ /// Rules that determine if this trigger can run.
+ ///
+ public TriggerRuleBase[] Rules { get; set; }
+
+ ///
+ /// Run trigger for existing incidents (received a duplicate exception)
+ ///
+ public bool RunForExistingIncidents { get; set; }
+
+ ///
+ /// Run trigger for new incidents (i.e. received a new unique exception)
+ ///
+ public bool RunForNewIncidents { get; set; }
+
+ ///
+ /// Run for incidents that is closed but received a new error report.
+ ///
+ public bool RunForReOpenedIncidents { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Modules/Triggers/Commands/DeleteTrigger.cs b/src/Server/Coderr.Server.Api/Modules/Triggers/Commands/DeleteTrigger.cs
similarity index 79%
rename from src/Server/OneTrueError.Api/Modules/Triggers/Commands/DeleteTrigger.cs
rename to src/Server/Coderr.Server.Api/Modules/Triggers/Commands/DeleteTrigger.cs
index 5eeb4cff..d17424f5 100644
--- a/src/Server/OneTrueError.Api/Modules/Triggers/Commands/DeleteTrigger.cs
+++ b/src/Server/Coderr.Server.Api/Modules/Triggers/Commands/DeleteTrigger.cs
@@ -1,26 +1,26 @@
-using System;
-using DotNetCqs;
-
-namespace OneTrueError.Api.Modules.Triggers.Commands
-{
- ///
- /// Delete a trigger
- ///
- public class DeleteTrigger : Command
- {
- ///
- /// Creates a new instance of .
- ///
- /// primary key
- public DeleteTrigger(int id)
- {
- if (id <= 0) throw new ArgumentOutOfRangeException("id");
- Id = id;
- }
-
- ///
- /// Primary key
- ///
- public int Id { get; private set; }
- }
+using System;
+
+namespace Coderr.Server.Api.Modules.Triggers.Commands
+{
+ ///
+ /// Delete a trigger
+ ///
+ [Message]
+ public class DeleteTrigger
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// primary key
+ public DeleteTrigger(int id)
+ {
+ if (id <= 0) throw new ArgumentOutOfRangeException("id");
+ Id = id;
+ }
+
+ ///
+ /// Primary key
+ ///
+ public int Id { get; private set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Modules/Triggers/Commands/UpdateTrigger.cs b/src/Server/Coderr.Server.Api/Modules/Triggers/Commands/UpdateTrigger.cs
similarity index 91%
rename from src/Server/OneTrueError.Api/Modules/Triggers/Commands/UpdateTrigger.cs
rename to src/Server/Coderr.Server.Api/Modules/Triggers/Commands/UpdateTrigger.cs
index 298e5434..e3e88deb 100644
--- a/src/Server/OneTrueError.Api/Modules/Triggers/Commands/UpdateTrigger.cs
+++ b/src/Server/Coderr.Server.Api/Modules/Triggers/Commands/UpdateTrigger.cs
@@ -1,78 +1,78 @@
-using System;
-using DotNetCqs;
-
-namespace OneTrueError.Api.Modules.Triggers.Commands
-{
- ///
- /// Update an existing trigger
- ///
- public class UpdateTrigger : Command
- {
- ///
- /// Creates a new instance of .
- ///
- /// trigger identity.
- /// Trigger name
- public UpdateTrigger(int id, string name)
- {
- if (name == null) throw new ArgumentNullException("name");
- if (id <= 0) throw new ArgumentOutOfRangeException("id");
-
- Id = id;
- Name = name;
- }
-
- ///
- /// Serialization constructor
- ///
- protected UpdateTrigger()
- {
- }
-
- ///
- /// Actions to run
- ///
- public TriggerActionDataDTO[] Actions { get; set; }
-
- ///
- /// What the trigger does and why
- ///
- public string Description { get; set; }
-
- ///
- /// Primary key
- ///
- public int Id { get; private set; }
-
- ///
- /// Action to take after all have run.
- ///
- public LastTriggerActionDTO LastTriggerAction { get; set; }
-
-
- ///
- /// Trigger name.
- ///
- public string Name { get; private set; }
-
- ///
- /// Rules that determine if this trigger can run.
- ///
- public TriggerRuleBase[] Rules { get; set; }
-
- ///
- /// Run trigger for existing incidents (received a duplicate exception)
- ///
- public bool RunForExistingIncidents { get; set; }
-
- ///
- /// Run trigger for new incidents (i.e. received a new unique exception)
- ///
- public bool RunForNewIncidents { get; set; }
-
- ///
- /// Run for incidents that is closed but received a new error report.
- ///
- public bool RunForReOpenedIncidents { get; set; }
- }
+using System;
+
+namespace Coderr.Server.Api.Modules.Triggers.Commands
+{
+ ///
+ /// Update an existing trigger
+ ///
+ [Message]
+ public class UpdateTrigger
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// trigger identity.
+ /// Trigger name
+ public UpdateTrigger(int id, string name)
+ {
+ if (name == null) throw new ArgumentNullException("name");
+ if (id <= 0) throw new ArgumentOutOfRangeException("id");
+
+ Id = id;
+ Name = name;
+ }
+
+ ///
+ /// Serialization constructor
+ ///
+ protected UpdateTrigger()
+ {
+ }
+
+ ///
+ /// Actions to run
+ ///
+ public TriggerActionDataDTO[] Actions { get; set; }
+
+ ///
+ /// What the trigger does and why
+ ///
+ public string Description { get; set; }
+
+ ///
+ /// Primary key
+ ///
+ public int Id { get; private set; }
+
+ ///
+ /// Action to take after all have run.
+ ///
+ public LastTriggerActionDTO LastTriggerAction { get; set; }
+
+
+ ///
+ /// Trigger name.
+ ///
+ public string Name { get; private set; }
+
+ ///
+ /// Rules that determine if this trigger can run.
+ ///
+ public TriggerRuleBase[] Rules { get; set; }
+
+ ///
+ /// Run trigger for existing incidents (received a duplicate exception)
+ ///
+ public bool RunForExistingIncidents { get; set; }
+
+ ///
+ /// Run trigger for new incidents (i.e. received a new unique exception)
+ ///
+ public bool RunForNewIncidents { get; set; }
+
+ ///
+ /// Run for incidents that is closed but received a new error report.
+ ///
+ public bool RunForReOpenedIncidents { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Modules/Triggers/LastTriggerActionDTO.cs b/src/Server/Coderr.Server.Api/Modules/Triggers/LastTriggerActionDTO.cs
similarity index 84%
rename from src/Server/OneTrueError.Api/Modules/Triggers/LastTriggerActionDTO.cs
rename to src/Server/Coderr.Server.Api/Modules/Triggers/LastTriggerActionDTO.cs
index a490a6e2..dc84aec8 100644
--- a/src/Server/OneTrueError.Api/Modules/Triggers/LastTriggerActionDTO.cs
+++ b/src/Server/Coderr.Server.Api/Modules/Triggers/LastTriggerActionDTO.cs
@@ -1,18 +1,18 @@
-namespace OneTrueError.Api.Modules.Triggers
-{
- ///
- /// What to do if all rules accepted the report.
- ///
- public enum LastTriggerActionDTO
- {
- ///
- /// Execute trigger actions.
- ///
- ExecuteActions,
-
- ///
- /// Abort the trigger
- ///
- AbortTrigger
- }
+namespace Coderr.Server.Api.Modules.Triggers
+{
+ ///
+ /// What to do if all rules accepted the report.
+ ///
+ public enum LastTriggerActionDTO
+ {
+ ///
+ /// Execute trigger actions.
+ ///
+ ExecuteActions,
+
+ ///
+ /// Abort the trigger
+ ///
+ AbortTrigger
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Modules/Triggers/Queries/GetContextCollectionMetadata.cs b/src/Server/Coderr.Server.Api/Modules/Triggers/Queries/GetContextCollectionMetadata.cs
similarity index 91%
rename from src/Server/OneTrueError.Api/Modules/Triggers/Queries/GetContextCollectionMetadata.cs
rename to src/Server/Coderr.Server.Api/Modules/Triggers/Queries/GetContextCollectionMetadata.cs
index e6ccc33d..c021454b 100644
--- a/src/Server/OneTrueError.Api/Modules/Triggers/Queries/GetContextCollectionMetadata.cs
+++ b/src/Server/Coderr.Server.Api/Modules/Triggers/Queries/GetContextCollectionMetadata.cs
@@ -1,27 +1,28 @@
-using System;
-using DotNetCqs;
-
-namespace OneTrueError.Api.Modules.Triggers.Queries
-{
- ///
- /// Get metadata (context collection information)
- ///
- public class GetContextCollectionMetadata : Query
- {
- ///
- /// Creates a new instance of .
- ///
- /// applicationId
- /// applicationId
- public GetContextCollectionMetadata(int applicationId)
- {
- if (applicationId <= 0) throw new ArgumentOutOfRangeException("applicationId");
- ApplicationId = applicationId;
- }
-
- ///
- /// Application to get info for.
- ///
- public int ApplicationId { get; private set; }
- }
+using System;
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Modules.Triggers.Queries
+{
+ ///
+ /// Get metadata (context collection information)
+ ///
+ [Message]
+ public class GetContextCollectionMetadata : Query
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// applicationId
+ /// applicationId
+ public GetContextCollectionMetadata(int applicationId)
+ {
+ if (applicationId <= 0) throw new ArgumentOutOfRangeException("applicationId");
+ ApplicationId = applicationId;
+ }
+
+ ///
+ /// Application to get info for.
+ ///
+ public int ApplicationId { get; private set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Modules/Triggers/Queries/GetContextCollectionMetadataItem.cs b/src/Server/Coderr.Server.Api/Modules/Triggers/Queries/GetContextCollectionMetadataItem.cs
similarity index 85%
rename from src/Server/OneTrueError.Api/Modules/Triggers/Queries/GetContextCollectionMetadataItem.cs
rename to src/Server/Coderr.Server.Api/Modules/Triggers/Queries/GetContextCollectionMetadataItem.cs
index e1d879d9..aee9a2b6 100644
--- a/src/Server/OneTrueError.Api/Modules/Triggers/Queries/GetContextCollectionMetadataItem.cs
+++ b/src/Server/Coderr.Server.Api/Modules/Triggers/Queries/GetContextCollectionMetadataItem.cs
@@ -1,18 +1,18 @@
-namespace OneTrueError.Api.Modules.Triggers.Queries
-{
- ///
- /// Result item for
- ///
- public class GetContextCollectionMetadataItem
- {
- ///
- /// Context name
- ///
- public string Name { get; set; }
-
- ///
- /// Property names
- ///
- public string[] Properties { get; set; }
- }
+namespace Coderr.Server.Api.Modules.Triggers.Queries
+{
+ ///
+ /// Result item for
+ ///
+ public class GetContextCollectionMetadataItem
+ {
+ ///
+ /// Context name
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// Property names
+ ///
+ public string[] Properties { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Modules/Triggers/Queries/GetTrigger.cs b/src/Server/Coderr.Server.Api/Modules/Triggers/Queries/GetTrigger.cs
similarity index 90%
rename from src/Server/OneTrueError.Api/Modules/Triggers/Queries/GetTrigger.cs
rename to src/Server/Coderr.Server.Api/Modules/Triggers/Queries/GetTrigger.cs
index 49f45340..90562237 100644
--- a/src/Server/OneTrueError.Api/Modules/Triggers/Queries/GetTrigger.cs
+++ b/src/Server/Coderr.Server.Api/Modules/Triggers/Queries/GetTrigger.cs
@@ -1,34 +1,35 @@
-using System;
-using DotNetCqs;
-
-namespace OneTrueError.Api.Modules.Triggers.Queries
-{
- ///
- /// Get a configured trigger
- ///
- public class GetTrigger : Query
- {
- ///
- /// Creates a new instance of .
- ///
- /// trigger id
- /// id
- public GetTrigger(int id)
- {
- if (id <= 0) throw new ArgumentOutOfRangeException("id");
- Id = id;
- }
-
- ///
- /// Serialization constructor
- ///
- protected GetTrigger()
- {
- }
-
- ///
- /// Triggger id
- ///
- public int Id { get; set; }
- }
+using System;
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Modules.Triggers.Queries
+{
+ ///
+ /// Get a configured trigger
+ ///
+ [Message]
+ public class GetTrigger : Query
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// trigger id
+ /// id
+ public GetTrigger(int id)
+ {
+ if (id <= 0) throw new ArgumentOutOfRangeException("id");
+ Id = id;
+ }
+
+ ///
+ /// Serialization constructor
+ ///
+ protected GetTrigger()
+ {
+ }
+
+ ///
+ /// Triggger id
+ ///
+ public int Id { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Modules/Triggers/Queries/GetTriggerDTO.cs b/src/Server/Coderr.Server.Api/Modules/Triggers/Queries/GetTriggerDTO.cs
similarity index 93%
rename from src/Server/OneTrueError.Api/Modules/Triggers/Queries/GetTriggerDTO.cs
rename to src/Server/Coderr.Server.Api/Modules/Triggers/Queries/GetTriggerDTO.cs
index f44a4955..76cd7837 100644
--- a/src/Server/OneTrueError.Api/Modules/Triggers/Queries/GetTriggerDTO.cs
+++ b/src/Server/Coderr.Server.Api/Modules/Triggers/Queries/GetTriggerDTO.cs
@@ -1,58 +1,58 @@
-namespace OneTrueError.Api.Modules.Triggers.Queries
-{
- ///
- /// Result for
- ///
- public class GetTriggerDTO
- {
- ///
- /// Actions to take if all rules says OK.
- ///
- public TriggerActionDataDTO[] Actions { get; set; }
-
- ///
- /// Application that the trigger is for.
- ///
- public int ApplicationId { get; set; }
-
- ///
- /// What the trigger does.
- ///
- public string Description { get; set; }
-
- ///
- /// Trigger id
- ///
- public int Id { get; set; }
-
- ///
- /// Decision to use if all rules have been passed.
- ///
- public LastTriggerActionDTO LastTriggerAction { get; set; }
-
- ///
- /// Trigger name
- ///
- public string Name { get; set; }
-
- ///
- /// Rules deciding if actions can be run.
- ///
- public TriggerRuleBase[] Rules { get; set; }
-
- ///
- /// Run for incidents that already has one or more reports.
- ///
- public bool RunForExistingIncidents { get; set; }
-
- ///
- /// Run trigger for new incidents (got a new unqiue exception)
- ///
- public bool RunForNewIncidents { get; set; }
-
- ///
- /// Run when a closed incident get its first new report.
- ///
- public bool RunForReOpenedIncidents { get; set; }
- }
+namespace Coderr.Server.Api.Modules.Triggers.Queries
+{
+ ///
+ /// Result for
+ ///
+ public class GetTriggerDTO
+ {
+ ///
+ /// Actions to take if all rules says OK.
+ ///
+ public TriggerActionDataDTO[] Actions { get; set; }
+
+ ///
+ /// Application that the trigger is for.
+ ///
+ public int ApplicationId { get; set; }
+
+ ///
+ /// What the trigger does.
+ ///
+ public string Description { get; set; }
+
+ ///
+ /// Trigger id
+ ///
+ public int Id { get; set; }
+
+ ///
+ /// Decision to use if all rules have been passed.
+ ///
+ public LastTriggerActionDTO LastTriggerAction { get; set; }
+
+ ///
+ /// Trigger name
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// Rules deciding if actions can be run.
+ ///
+ public TriggerRuleBase[] Rules { get; set; }
+
+ ///
+ /// Run for incidents that already has one or more reports.
+ ///
+ public bool RunForExistingIncidents { get; set; }
+
+ ///
+ /// Run trigger for new incidents (got a new unqiue exception)
+ ///
+ public bool RunForNewIncidents { get; set; }
+
+ ///
+ /// Run when a closed incident get its first new report.
+ ///
+ public bool RunForReOpenedIncidents { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Modules/Triggers/Queries/GetTriggersForApplication.cs b/src/Server/Coderr.Server.Api/Modules/Triggers/Queries/GetTriggersForApplication.cs
similarity index 92%
rename from src/Server/OneTrueError.Api/Modules/Triggers/Queries/GetTriggersForApplication.cs
rename to src/Server/Coderr.Server.Api/Modules/Triggers/Queries/GetTriggersForApplication.cs
index 1647b5a8..e861069f 100644
--- a/src/Server/OneTrueError.Api/Modules/Triggers/Queries/GetTriggersForApplication.cs
+++ b/src/Server/Coderr.Server.Api/Modules/Triggers/Queries/GetTriggersForApplication.cs
@@ -1,34 +1,35 @@
-using System;
-using DotNetCqs;
-
-namespace OneTrueError.Api.Modules.Triggers.Queries
-{
- ///
- /// Get all triggers for an application
- ///
- public class GetTriggersForApplication : Query
- {
- ///
- /// Creates a new instance of .
- ///
- /// application to get triggers for
- /// applicationId
- public GetTriggersForApplication(int applicationId)
- {
- if (applicationId <= 0) throw new ArgumentOutOfRangeException("applicationId");
- ApplicationId = applicationId;
- }
-
- ///
- /// Serialization constructor.
- ///
- protected GetTriggersForApplication()
- {
- }
-
- ///
- /// Application
- ///
- public int ApplicationId { get; set; }
- }
+using System;
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Modules.Triggers.Queries
+{
+ ///
+ /// Get all triggers for an application
+ ///
+ [Message]
+ public class GetTriggersForApplication : Query
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// application to get triggers for
+ /// applicationId
+ public GetTriggersForApplication(int applicationId)
+ {
+ if (applicationId <= 0) throw new ArgumentOutOfRangeException("applicationId");
+ ApplicationId = applicationId;
+ }
+
+ ///
+ /// Serialization constructor.
+ ///
+ protected GetTriggersForApplication()
+ {
+ }
+
+ ///
+ /// Application
+ ///
+ public int ApplicationId { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Modules/Triggers/TriggerActionDataDTO.cs b/src/Server/Coderr.Server.Api/Modules/Triggers/TriggerActionDataDTO.cs
similarity index 84%
rename from src/Server/OneTrueError.Api/Modules/Triggers/TriggerActionDataDTO.cs
rename to src/Server/Coderr.Server.Api/Modules/Triggers/TriggerActionDataDTO.cs
index 2b1f5d90..198c3f06 100644
--- a/src/Server/OneTrueError.Api/Modules/Triggers/TriggerActionDataDTO.cs
+++ b/src/Server/Coderr.Server.Api/Modules/Triggers/TriggerActionDataDTO.cs
@@ -1,18 +1,18 @@
-namespace OneTrueError.Api.Modules.Triggers
-{
- ///
- /// DTO
- ///
- public class TriggerActionDataDTO
- {
- ///
- /// Action context
- ///
- public string ActionContext { get; set; }
-
- ///
- /// Action name
- ///
- public string ActionName { get; set; }
- }
+namespace Coderr.Server.Api.Modules.Triggers
+{
+ ///
+ /// DTO
+ ///
+ public class TriggerActionDataDTO
+ {
+ ///
+ /// Action context
+ ///
+ public string ActionContext { get; set; }
+
+ ///
+ /// Action name
+ ///
+ public string ActionName { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Modules/Triggers/TriggerContextRule.cs b/src/Server/Coderr.Server.Api/Modules/Triggers/TriggerContextRule.cs
similarity index 88%
rename from src/Server/OneTrueError.Api/Modules/Triggers/TriggerContextRule.cs
rename to src/Server/Coderr.Server.Api/Modules/Triggers/TriggerContextRule.cs
index a004d48e..1543db92 100644
--- a/src/Server/OneTrueError.Api/Modules/Triggers/TriggerContextRule.cs
+++ b/src/Server/Coderr.Server.Api/Modules/Triggers/TriggerContextRule.cs
@@ -1,23 +1,23 @@
-namespace OneTrueError.Api.Modules.Triggers
-{
- ///
- /// Context when doing the filtering
- ///
- public class TriggerContextRule : TriggerRuleBase
- {
- ///
- /// Context name currently being inspected
- ///
- public string ContextName { get; set; }
-
- ///
- /// Property in that context
- ///
- public string PropertyName { get; set; }
-
- ///
- /// Value
- ///
- public string PropertyValue { get; set; }
- }
+namespace Coderr.Server.Api.Modules.Triggers
+{
+ ///
+ /// Context when doing the filtering
+ ///
+ public class TriggerContextRule : TriggerRuleBase
+ {
+ ///
+ /// Context name currently being inspected
+ ///
+ public string ContextName { get; set; }
+
+ ///
+ /// Property in that context
+ ///
+ public string PropertyName { get; set; }
+
+ ///
+ /// Value
+ ///
+ public string PropertyValue { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Modules/Triggers/TriggerDTO.cs b/src/Server/Coderr.Server.Api/Modules/Triggers/TriggerDTO.cs
similarity index 89%
rename from src/Server/OneTrueError.Api/Modules/Triggers/TriggerDTO.cs
rename to src/Server/Coderr.Server.Api/Modules/Triggers/TriggerDTO.cs
index 7502c2c0..88ebbd9b 100644
--- a/src/Server/OneTrueError.Api/Modules/Triggers/TriggerDTO.cs
+++ b/src/Server/Coderr.Server.Api/Modules/Triggers/TriggerDTO.cs
@@ -1,28 +1,28 @@
-namespace OneTrueError.Api.Modules.Triggers
-{
- ///
- /// Trigger DTO
- ///
- public class TriggerDTO
- {
- ///
- /// Description (typically why it was created and what it should do)
- ///
- public string Description { get; set; }
-
- ///
- /// Identity
- ///
- public string Id { get; set; }
-
- ///
- /// Trigger name
- ///
- public string Name { get; set; }
-
- ///
- /// Short summary
- ///
- public string Summary { get; set; }
- }
+namespace Coderr.Server.Api.Modules.Triggers
+{
+ ///
+ /// Trigger DTO
+ ///
+ public class TriggerDTO
+ {
+ ///
+ /// Description (typically why it was created and what it should do)
+ ///
+ public string Description { get; set; }
+
+ ///
+ /// Identity
+ ///
+ public string Id { get; set; }
+
+ ///
+ /// Trigger name
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// Short summary
+ ///
+ public string Summary { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Modules/Triggers/TriggerExceptionRule.cs b/src/Server/Coderr.Server.Api/Modules/Triggers/TriggerExceptionRule.cs
similarity index 88%
rename from src/Server/OneTrueError.Api/Modules/Triggers/TriggerExceptionRule.cs
rename to src/Server/Coderr.Server.Api/Modules/Triggers/TriggerExceptionRule.cs
index 730da072..24551c92 100644
--- a/src/Server/OneTrueError.Api/Modules/Triggers/TriggerExceptionRule.cs
+++ b/src/Server/Coderr.Server.Api/Modules/Triggers/TriggerExceptionRule.cs
@@ -1,18 +1,18 @@
-namespace OneTrueError.Api.Modules.Triggers
-{
- ///
- /// Make a decision based on exception information
- ///
- public class TriggerExceptionRule : TriggerRuleBase
- {
- ///
- /// Field in the exception details that should be inspected (property name from the Exception class)
- ///
- public string FieldName { get; set; }
-
- ///
- /// Value that should be matched.
- ///
- public string Value { get; set; }
- }
+namespace Coderr.Server.Api.Modules.Triggers
+{
+ ///
+ /// Make a decision based on exception information
+ ///
+ public class TriggerExceptionRule : TriggerRuleBase
+ {
+ ///
+ /// Field in the exception details that should be inspected (property name from the Exception class)
+ ///
+ public string FieldName { get; set; }
+
+ ///
+ /// Value that should be matched.
+ ///
+ public string Value { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Modules/Triggers/TriggerFilterCondition.cs b/src/Server/Coderr.Server.Api/Modules/Triggers/TriggerFilterCondition.cs
similarity index 92%
rename from src/Server/OneTrueError.Api/Modules/Triggers/TriggerFilterCondition.cs
rename to src/Server/Coderr.Server.Api/Modules/Triggers/TriggerFilterCondition.cs
index 45ee5a69..1abb378b 100644
--- a/src/Server/OneTrueError.Api/Modules/Triggers/TriggerFilterCondition.cs
+++ b/src/Server/Coderr.Server.Api/Modules/Triggers/TriggerFilterCondition.cs
@@ -1,35 +1,35 @@
-using System.ComponentModel;
-
-namespace OneTrueError.Api.Modules.Triggers
-{
- ///
- /// Filter condition
- ///
- public enum TriggerFilterCondition
- {
- ///
- /// Inspected value should start with the filter string
- ///
- [Description("Starts with")] StartsWith,
-
- ///
- /// Inspected value should end with the filter string
- ///
- [Description("Ends with")] EndsWith,
-
- ///
- /// Inspected value should contain the filter string
- ///
- [Description("Contain")] Contains,
-
- ///
- /// Inspected value should not contain the filter string
- ///
- [Description("Do not contain")] DoNotContain,
-
- ///
- /// Inspected value should equal the filter string (case insensitive)
- ///
- [Description("Equals")] Equals
- }
+using System.ComponentModel;
+
+namespace Coderr.Server.Api.Modules.Triggers
+{
+ ///
+ /// Filter condition
+ ///
+ public enum TriggerFilterCondition
+ {
+ ///
+ /// Inspected value should start with the filter string
+ ///
+ [Description("Starts with")] StartsWith,
+
+ ///
+ /// Inspected value should end with the filter string
+ ///
+ [Description("Ends with")] EndsWith,
+
+ ///
+ /// Inspected value should contain the filter string
+ ///
+ [Description("Contain")] Contains,
+
+ ///
+ /// Inspected value should not contain the filter string
+ ///
+ [Description("Do not contain")] DoNotContain,
+
+ ///
+ /// Inspected value should equal the filter string (case insensitive)
+ ///
+ [Description("Equals")] Equals
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Modules/Triggers/TriggerRuleAction.cs b/src/Server/Coderr.Server.Api/Modules/Triggers/TriggerRuleAction.cs
similarity index 89%
rename from src/Server/OneTrueError.Api/Modules/Triggers/TriggerRuleAction.cs
rename to src/Server/Coderr.Server.Api/Modules/Triggers/TriggerRuleAction.cs
index d023dcc5..642d97cc 100644
--- a/src/Server/OneTrueError.Api/Modules/Triggers/TriggerRuleAction.cs
+++ b/src/Server/Coderr.Server.Api/Modules/Triggers/TriggerRuleAction.cs
@@ -1,23 +1,23 @@
-namespace OneTrueError.Api.Modules.Triggers
-{
- ///
- /// Action to take when a filter is apssed
- ///
- public enum TriggerRuleAction
- {
- ///
- /// Do not execute the trigger
- ///
- AbortTrigger,
-
- ///
- /// Middle manager principle: Lets delegate the decision to the next rule.
- ///
- ContinueWithNextRule,
-
- ///
- /// Do not check any more rules, just execute the god damn trigger.
- ///
- ExecuteActions
- }
+namespace Coderr.Server.Api.Modules.Triggers
+{
+ ///
+ /// Action to take when a filter is apssed
+ ///
+ public enum TriggerRuleAction
+ {
+ ///
+ /// Do not execute the trigger
+ ///
+ AbortTrigger,
+
+ ///
+ /// Middle manager principle: Lets delegate the decision to the next rule.
+ ///
+ ContinueWithNextRule,
+
+ ///
+ /// Do not check any more rules, just execute the god damn trigger.
+ ///
+ ExecuteActions
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Modules/Triggers/TriggerRuleBase.cs b/src/Server/Coderr.Server.Api/Modules/Triggers/TriggerRuleBase.cs
similarity index 86%
rename from src/Server/OneTrueError.Api/Modules/Triggers/TriggerRuleBase.cs
rename to src/Server/Coderr.Server.Api/Modules/Triggers/TriggerRuleBase.cs
index 3b27a308..05138787 100644
--- a/src/Server/OneTrueError.Api/Modules/Triggers/TriggerRuleBase.cs
+++ b/src/Server/Coderr.Server.Api/Modules/Triggers/TriggerRuleBase.cs
@@ -1,18 +1,18 @@
-namespace OneTrueError.Api.Modules.Triggers
-{
- ///
- /// Base class for rules.
- ///
- public class TriggerRuleBase
- {
- ///
- /// Filter that should be passed
- ///
- public TriggerFilterCondition Filter { get; set; }
-
- ///
- /// Did we pass the filter? Then do this.
- ///
- public TriggerRuleAction ResultToUse { get; set; }
- }
+namespace Coderr.Server.Api.Modules.Triggers
+{
+ ///
+ /// Base class for rules.
+ ///
+ public class TriggerRuleBase
+ {
+ ///
+ /// Filter that should be passed
+ ///
+ public TriggerFilterCondition Filter { get; set; }
+
+ ///
+ /// Did we pass the filter? Then do this.
+ ///
+ public TriggerRuleAction ResultToUse { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Modules/Versions/Queries/GetApplicationVersions.cs b/src/Server/Coderr.Server.Api/Modules/Versions/Queries/GetApplicationVersions.cs
new file mode 100644
index 00000000..cc90599e
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Modules/Versions/Queries/GetApplicationVersions.cs
@@ -0,0 +1,28 @@
+using System;
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Modules.Versions.Queries
+{
+ ///
+ /// Get all application versions that we've received incidents for
+ ///
+ [Message]
+ public class GetApplicationVersions : Query
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// application to get versions for
+ ///
+ public GetApplicationVersions(int applicationId)
+ {
+ if (applicationId <= 0) throw new ArgumentOutOfRangeException("applicationId");
+ ApplicationId = applicationId;
+ }
+
+ ///
+ /// Application id
+ ///
+ public int ApplicationId { get; private set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Modules/Versions/Queries/GetApplicationVersionsResult.cs b/src/Server/Coderr.Server.Api/Modules/Versions/Queries/GetApplicationVersionsResult.cs
new file mode 100644
index 00000000..b261906e
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Modules/Versions/Queries/GetApplicationVersionsResult.cs
@@ -0,0 +1,13 @@
+namespace Coderr.Server.Api.Modules.Versions.Queries
+{
+ ///
+ /// Result for
+ ///
+ public class GetApplicationVersionsResult
+ {
+ ///
+ /// All versions
+ ///
+ public GetApplicationVersionsResultItem[] Items { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Modules/Versions/Queries/GetApplicationVersionsResultItem.cs b/src/Server/Coderr.Server.Api/Modules/Versions/Queries/GetApplicationVersionsResultItem.cs
new file mode 100644
index 00000000..d6b7c725
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Modules/Versions/Queries/GetApplicationVersionsResultItem.cs
@@ -0,0 +1,35 @@
+using System;
+
+namespace Coderr.Server.Api.Modules.Versions.Queries
+{
+ ///
+ /// Version information
+ ///
+ public class GetApplicationVersionsResultItem
+ {
+ ///
+ /// When we received the first incident for this application
+ ///
+ public DateTime FirstReportReceivedAtUtc { get; set; }
+
+ ///
+ /// Number of new incidents
+ ///
+ public int IncidentCount { get; set; }
+
+ ///
+ /// When we received the most recent report for this version
+ ///
+ public DateTime LastReportReceivedAtUtc { get; set; }
+
+ ///
+ /// Number of reports (for old and new incidents)
+ ///
+ public int ReportCount { get; set; }
+
+ ///
+ /// Version string (x.x.x.x)
+ ///
+ public string Version { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Modules/Versions/Queries/GetVersionHistory.cs b/src/Server/Coderr.Server.Api/Modules/Versions/Queries/GetVersionHistory.cs
new file mode 100644
index 00000000..47b2b771
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Modules/Versions/Queries/GetVersionHistory.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Modules.Versions.Queries
+{
+ [Message]
+ public class GetVersionHistory : Query
+ {
+ public int ApplicationId { get; set; }
+ public DateTime? FromDate { get; set; }
+ public DateTime? ToDate { get; set; }
+ }
+}
diff --git a/src/Server/Coderr.Server.Api/Modules/Versions/Queries/GetVersionHistoryResult.cs b/src/Server/Coderr.Server.Api/Modules/Versions/Queries/GetVersionHistoryResult.cs
new file mode 100644
index 00000000..4b2f60a8
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Modules/Versions/Queries/GetVersionHistoryResult.cs
@@ -0,0 +1,23 @@
+using System.Collections.Generic;
+
+namespace Coderr.Server.Api.Modules.Versions.Queries
+{
+ [Message]
+ public class GetVersionHistoryResult
+ {
+ ///
+ /// Year-Month
+ ///
+ public string[] Dates { get; set; }
+
+ ///
+ /// Key = version name, Value = number of incidents for the month
+ ///
+ public GetVersionHistoryResultSet[] IncidentCounts { get; set; }
+
+ ///
+ /// Key = version name, Value = number of error reports for the month
+ ///
+ public GetVersionHistoryResultSet[] ReportCounts { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Modules/Versions/Queries/GetVersionHistoryResultItem.cs b/src/Server/Coderr.Server.Api/Modules/Versions/Queries/GetVersionHistoryResultItem.cs
new file mode 100644
index 00000000..1f0974e1
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Modules/Versions/Queries/GetVersionHistoryResultItem.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Coderr.Server.Api.Modules.Versions.Queries
+{
+ public class GetVersionHistoryResultItem
+ {
+ public int IncindentCount { get; set; }
+ public int ReportCount { get; set; }
+ public DateTime LastUpdateAtUtc { get; set; }
+ public string Version { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Modules/Versions/Queries/GetVersionHistoryResultMonth.cs b/src/Server/Coderr.Server.Api/Modules/Versions/Queries/GetVersionHistoryResultMonth.cs
new file mode 100644
index 00000000..15a9ad8b
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Modules/Versions/Queries/GetVersionHistoryResultMonth.cs
@@ -0,0 +1,11 @@
+using System;
+using System.Collections.Generic;
+
+namespace Coderr.Server.Api.Modules.Versions.Queries
+{
+ public class GetVersionHistoryResultMonth
+ {
+ public DateTime YearMonth { get; set; }
+ public IList Items { get; set; } = new List();
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Modules/Versions/Queries/GetVersionHistoryResultSet.cs b/src/Server/Coderr.Server.Api/Modules/Versions/Queries/GetVersionHistoryResultSet.cs
new file mode 100644
index 00000000..c6070030
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Modules/Versions/Queries/GetVersionHistoryResultSet.cs
@@ -0,0 +1,8 @@
+namespace Coderr.Server.Api.Modules.Versions.Queries
+{
+ public class GetVersionHistoryResultSet
+ {
+ public string Name { get; set; }
+ public int[] Values { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Modules/Whitelists/Commands/AddEntry.cs b/src/Server/Coderr.Server.Api/Modules/Whitelists/Commands/AddEntry.cs
new file mode 100644
index 00000000..172ed4c1
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Modules/Whitelists/Commands/AddEntry.cs
@@ -0,0 +1,24 @@
+namespace Coderr.Server.Api.Modules.Whitelists.Commands
+{
+ ///
+ /// Add a domain that may post error reports without using a shared secret (javascript applications)
+ ///
+ [Command]
+ public class AddEntry
+ {
+ ///
+ /// Applications that the domain is allowed for.
+ ///
+ public int[] ApplicationIds { get; set; } = new int[0];
+
+ ///
+ /// For instance yourdomain.com.
+ ///
+ public string DomainName { get; set; }
+
+ ///
+ /// To manually specify which IP addresses the domain matches.
+ ///
+ public string[] IpAddresses { get; set; } = new string[0];
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Modules/Whitelists/Commands/EditEntry.cs b/src/Server/Coderr.Server.Api/Modules/Whitelists/Commands/EditEntry.cs
new file mode 100644
index 00000000..f39fa81f
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Modules/Whitelists/Commands/EditEntry.cs
@@ -0,0 +1,25 @@
+namespace Coderr.Server.Api.Modules.Whitelists.Commands
+{
+ ///
+ /// Edit a domain that may post error reports without using a shared secret (javascript applications)
+ ///
+ [Command]
+ public class EditEntry
+ {
+ ///
+ /// PK for the entry being edited.
+ ///
+ public int Id { get; set; }
+
+ ///
+ /// Applications that the domain is allowed for.
+ ///
+ public int[] ApplicationIds { get; set; } = new int[0];
+
+
+ ///
+ /// Only manually specified ip addresses.
+ ///
+ public string[] IpAddresses { get; set; } = new string[0];
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Modules/Whitelists/Commands/RemoveEntry.cs b/src/Server/Coderr.Server.Api/Modules/Whitelists/Commands/RemoveEntry.cs
new file mode 100644
index 00000000..33d83a6b
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Modules/Whitelists/Commands/RemoveEntry.cs
@@ -0,0 +1,14 @@
+namespace Coderr.Server.Api.Modules.Whitelists.Commands
+{
+ ///
+ /// Remove a previously added white list entry
+ ///
+ [Command]
+ public class RemoveEntry
+ {
+ ///
+ /// Id of the entry.
+ ///
+ public int Id { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Modules/Whitelists/Queries/GetWhitelistEntries.cs b/src/Server/Coderr.Server.Api/Modules/Whitelists/Queries/GetWhitelistEntries.cs
new file mode 100644
index 00000000..759c4c90
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Modules/Whitelists/Queries/GetWhitelistEntries.cs
@@ -0,0 +1,21 @@
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Modules.Whitelists.Queries
+{
+ ///
+ /// Get whitelist either by application id or DomainName
+ ///
+ [Message]
+ public class GetWhitelistEntries : Query
+ {
+ ///
+ /// Limit result to this application only
+ ///
+ public int? ApplicationId { get; set; }
+
+ ///
+ /// Limit result to this domain name only
+ ///
+ public string DomainName { get; set; }
+ }
+}
diff --git a/src/Server/Coderr.Server.Api/Modules/Whitelists/Queries/GetWhitelistEntriesResult.cs b/src/Server/Coderr.Server.Api/Modules/Whitelists/Queries/GetWhitelistEntriesResult.cs
new file mode 100644
index 00000000..b6e709ae
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Modules/Whitelists/Queries/GetWhitelistEntriesResult.cs
@@ -0,0 +1,10 @@
+namespace Coderr.Server.Api.Modules.Whitelists.Queries
+{
+ ///
+ /// Result for .
+ ///
+ public class GetWhitelistEntriesResult
+ {
+ public GetWhitelistEntriesResultItem[] Entries { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Modules/Whitelists/Queries/GetWhitelistEntriesResultItem.cs b/src/Server/Coderr.Server.Api/Modules/Whitelists/Queries/GetWhitelistEntriesResultItem.cs
new file mode 100644
index 00000000..27b726f2
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Modules/Whitelists/Queries/GetWhitelistEntriesResultItem.cs
@@ -0,0 +1,13 @@
+namespace Coderr.Server.Api.Modules.Whitelists.Queries
+{
+ ///
+ /// Entry for
+ ///
+ public class GetWhitelistEntriesResultItem
+ {
+ public int Id { get; set; }
+ public GetWhitelistEntriesResultItemIp[] IpAddresses { get; set; }
+ public GetWhitelistEntriesResultItemApp[] Applications { get; set; }
+ public string DomainName { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Modules/Whitelists/Queries/GetWhitelistEntriesResultItemApp.cs b/src/Server/Coderr.Server.Api/Modules/Whitelists/Queries/GetWhitelistEntriesResultItemApp.cs
new file mode 100644
index 00000000..b43a9e73
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Modules/Whitelists/Queries/GetWhitelistEntriesResultItemApp.cs
@@ -0,0 +1,8 @@
+namespace Coderr.Server.Api.Modules.Whitelists.Queries
+{
+ public class GetWhitelistEntriesResultItemApp
+ {
+ public int ApplicationId { get; set; }
+ public string Name { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Modules/Whitelists/Queries/GetWhitelistEntriesResultItemIp.cs b/src/Server/Coderr.Server.Api/Modules/Whitelists/Queries/GetWhitelistEntriesResultItemIp.cs
new file mode 100644
index 00000000..97845852
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Modules/Whitelists/Queries/GetWhitelistEntriesResultItemIp.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace Coderr.Server.Api.Modules.Whitelists.Queries
+{
+ public class GetWhitelistEntriesResultItemIp
+ {
+ public string Address { get; set; }
+ public DateTime UpdatedAtUtc { get; set; }
+ public ResultItemIpType Type { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Modules/Whitelists/Queries/ResultItemIpType.cs b/src/Server/Coderr.Server.Api/Modules/Whitelists/Queries/ResultItemIpType.cs
new file mode 100644
index 00000000..89c4db4d
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Modules/Whitelists/Queries/ResultItemIpType.cs
@@ -0,0 +1,23 @@
+namespace Coderr.Server.Api.Modules.Whitelists.Queries
+{
+ ///
+ /// Typ of stored IP record.
+ ///
+ public enum ResultItemIpType
+ {
+ ///
+ /// Added when doing a lookup for the domain
+ ///
+ Lookup = 0,
+
+ ///
+ /// Manually specified by the user
+ ///
+ Manual = 1,
+
+ ///
+ /// We got a request from this IP and a lookup didn't match it.
+ ///
+ Denied = 2
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/NamespaceDoc.cs b/src/Server/Coderr.Server.Api/NamespaceDoc.cs
new file mode 100644
index 00000000..e40430e3
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/NamespaceDoc.cs
@@ -0,0 +1,43 @@
+using System.Runtime.CompilerServices;
+
+namespace Coderr.Server.Api
+{
+ // This file is Generated by the tool MarkdownToNamespaceDoc. ReadMe.md is the master.
+
+ ///
+ /// API
+ ///
+ ///
+ /// The API is based on Command/Queries and events.
+ ///
+ /// Commands can be seen as the write model. All operations is done with the
+ /// help of commands. A command is not an atomic unit, but do in most cases represent an use case.
+ ///
+ ///
+ /// Queries are the read model in the application. They are used to fetch information. Queries are idempotent and
+ /// may not change
+ /// application state.
+ ///
+ ///
+ /// Events are used to allow different parts of the application to talk. The publisher are not aware of if there
+ /// are any
+ /// subscribers or how many there are. The subscriber have no knowledge about who published the event.
+ ///
+ /// Implementations
+ ///
+ /// There is a tool in the "Tool" root folder which are used to generate Typescript classes from these
+ /// APIs. The .ts files can be
+ /// invoked using Ajax directly from the web.
+ ///
+ ///
+ /// You can also invoke the DTOs directly from your application using a HTTP client. Serialize the DTO as JSON and
+ /// then include
+ /// X-Cqs-Object-Type as a HTTP header. It should contain the assembly qualified type name of the DTO.
+ ///
+ /// Basic authentication is used. Thus we recommend that you run the site using SSL.
+ ///
+ [CompilerGenerated]
+ internal class NamespaceDoc
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/ReadMe.md b/src/Server/Coderr.Server.Api/ReadMe.md
similarity index 100%
rename from src/Server/OneTrueError.Api/ReadMe.md
rename to src/Server/Coderr.Server.Api/ReadMe.md
diff --git a/src/Server/OneTrueError.Api/Web/Feedback/Queries/GetFeedbackForApplication.cs b/src/Server/Coderr.Server.Api/Web/Feedback/Queries/GetFeedbackForApplication.cs
similarity index 92%
rename from src/Server/OneTrueError.Api/Web/Feedback/Queries/GetFeedbackForApplication.cs
rename to src/Server/Coderr.Server.Api/Web/Feedback/Queries/GetFeedbackForApplication.cs
index 42d6c2ab..1008fae1 100644
--- a/src/Server/OneTrueError.Api/Web/Feedback/Queries/GetFeedbackForApplication.cs
+++ b/src/Server/Coderr.Server.Api/Web/Feedback/Queries/GetFeedbackForApplication.cs
@@ -1,34 +1,35 @@
-using System;
-using DotNetCqs;
-
-namespace OneTrueError.Api.Web.Feedback.Queries
-{
- ///
- /// Get all feedback that is for a specific application
- ///
- public class GetFeedbackForApplicationPage : Query
- {
- ///
- /// Creates a new instance of .
- ///
- /// application id
- /// applicationId
- public GetFeedbackForApplicationPage(int applicationId)
- {
- if (applicationId <= 0) throw new ArgumentOutOfRangeException("applicationId");
- ApplicationId = applicationId;
- }
-
- ///
- /// Serialization constructor
- ///
- protected GetFeedbackForApplicationPage()
- {
- }
-
- ///
- /// Application id
- ///
- public int ApplicationId { get; private set; }
- }
+using System;
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Web.Feedback.Queries
+{
+ ///
+ /// Get all feedback that is for a specific application
+ ///
+ [Message]
+ public class GetFeedbackForApplicationPage : Query
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// application id
+ /// applicationId
+ public GetFeedbackForApplicationPage(int applicationId)
+ {
+ if (applicationId <= 0) throw new ArgumentOutOfRangeException("applicationId");
+ ApplicationId = applicationId;
+ }
+
+ ///
+ /// Serialization constructor
+ ///
+ protected GetFeedbackForApplicationPage()
+ {
+ }
+
+ ///
+ /// Application id
+ ///
+ public int ApplicationId { get; private set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Web/Feedback/Queries/GetFeedbackForApplicationResult.cs b/src/Server/Coderr.Server.Api/Web/Feedback/Queries/GetFeedbackForApplicationResult.cs
similarity index 90%
rename from src/Server/OneTrueError.Api/Web/Feedback/Queries/GetFeedbackForApplicationResult.cs
rename to src/Server/Coderr.Server.Api/Web/Feedback/Queries/GetFeedbackForApplicationResult.cs
index 59891d3f..3b67f0a5 100644
--- a/src/Server/OneTrueError.Api/Web/Feedback/Queries/GetFeedbackForApplicationResult.cs
+++ b/src/Server/Coderr.Server.Api/Web/Feedback/Queries/GetFeedbackForApplicationResult.cs
@@ -1,26 +1,26 @@
-using System.Collections.Generic;
-
-namespace OneTrueError.Api.Web.Feedback.Queries
-{
- ///
- /// Result for
- ///
- public class GetFeedbackForApplicationPageResult
- {
- ///
- /// All emails (included in the first page)
- ///
- //TODO: crappy solution
- public List Emails { get; set; }
-
- ///
- /// items on this page
- ///
- public GetFeedbackForApplicationPageResultItem[] Items { get; set; }
-
- ///
- /// Total number of items
- ///
- public int TotalCount { get; set; }
- }
+using System.Collections.Generic;
+
+namespace Coderr.Server.Api.Web.Feedback.Queries
+{
+ ///
+ /// Result for
+ ///
+ public class GetFeedbackForApplicationPageResult
+ {
+ ///
+ /// All emails (included in the first page)
+ ///
+ //TODO: crappy solution
+ public List Emails { get; set; }
+
+ ///
+ /// items on this page
+ ///
+ public GetFeedbackForApplicationPageResultItem[] Items { get; set; }
+
+ ///
+ /// Total number of items
+ ///
+ public int TotalCount { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Web/Feedback/Queries/GetFeedbackForApplicationResultItem.cs b/src/Server/Coderr.Server.Api/Web/Feedback/Queries/GetFeedbackForApplicationResultItem.cs
similarity index 92%
rename from src/Server/OneTrueError.Api/Web/Feedback/Queries/GetFeedbackForApplicationResultItem.cs
rename to src/Server/Coderr.Server.Api/Web/Feedback/Queries/GetFeedbackForApplicationResultItem.cs
index ef53f4b8..3a978fab 100644
--- a/src/Server/OneTrueError.Api/Web/Feedback/Queries/GetFeedbackForApplicationResultItem.cs
+++ b/src/Server/Coderr.Server.Api/Web/Feedback/Queries/GetFeedbackForApplicationResultItem.cs
@@ -1,35 +1,35 @@
-using System;
-
-namespace OneTrueError.Api.Web.Feedback.Queries
-{
- ///
- /// Result item for .
- ///
- public class GetFeedbackForApplicationPageResultItem
- {
- ///
- /// Email adress to the user (if the user want to get status updates for the incident)
- ///
- public string EmailAddress { get; set; }
-
- ///
- /// Incident that the feedback belongs to
- ///
- public int IncidentId { get; set; }
-
- ///
- /// Incident name (typically first line of the exception message)
- ///
- public string IncidentName { get; set; }
-
- ///
- /// Error description written by the user that experienced the error.
- ///
- public string Message { get; set; }
-
- ///
- /// When the user wrote the feedback
- ///
- public DateTime WrittenAtUtc { get; set; }
- }
+using System;
+
+namespace Coderr.Server.Api.Web.Feedback.Queries
+{
+ ///
+ /// Result item for .
+ ///
+ public class GetFeedbackForApplicationPageResultItem
+ {
+ ///
+ /// Email adress to the user (if the user want to get status updates for the incident)
+ ///
+ public string EmailAddress { get; set; }
+
+ ///
+ /// Incident that the feedback belongs to
+ ///
+ public int IncidentId { get; set; }
+
+ ///
+ /// Incident name (typically first line of the exception message)
+ ///
+ public string IncidentName { get; set; }
+
+ ///
+ /// Error description written by the user that experienced the error.
+ ///
+ public string Message { get; set; }
+
+ ///
+ /// When the user wrote the feedback
+ ///
+ public DateTime WrittenAtUtc { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Web/Feedback/Queries/GetFeedbackForDashboardPage.cs b/src/Server/Coderr.Server.Api/Web/Feedback/Queries/GetFeedbackForDashboardPage.cs
similarity index 77%
rename from src/Server/OneTrueError.Api/Web/Feedback/Queries/GetFeedbackForDashboardPage.cs
rename to src/Server/Coderr.Server.Api/Web/Feedback/Queries/GetFeedbackForDashboardPage.cs
index 22ee815f..6d822f32 100644
--- a/src/Server/OneTrueError.Api/Web/Feedback/Queries/GetFeedbackForDashboardPage.cs
+++ b/src/Server/Coderr.Server.Api/Web/Feedback/Queries/GetFeedbackForDashboardPage.cs
@@ -1,11 +1,12 @@
-using DotNetCqs;
-
-namespace OneTrueError.Api.Web.Feedback.Queries
-{
- ///
- /// Get given feedback for all applications.
- ///
- public class GetFeedbackForDashboardPage : Query
- {
- }
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Web.Feedback.Queries
+{
+ ///
+ /// Get given feedback for all applications.
+ ///
+ [Message]
+ public class GetFeedbackForDashboardPage : Query
+ {
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Web/Feedback/Queries/GetFeedbackForDashboardPageResult.cs b/src/Server/Coderr.Server.Api/Web/Feedback/Queries/GetFeedbackForDashboardPageResult.cs
similarity index 90%
rename from src/Server/OneTrueError.Api/Web/Feedback/Queries/GetFeedbackForDashboardPageResult.cs
rename to src/Server/Coderr.Server.Api/Web/Feedback/Queries/GetFeedbackForDashboardPageResult.cs
index 63910c62..df3881f7 100644
--- a/src/Server/OneTrueError.Api/Web/Feedback/Queries/GetFeedbackForDashboardPageResult.cs
+++ b/src/Server/Coderr.Server.Api/Web/Feedback/Queries/GetFeedbackForDashboardPageResult.cs
@@ -1,25 +1,25 @@
-using System.Collections.Generic;
-
-namespace OneTrueError.Api.Web.Feedback.Queries
-{
- ///
- /// Result for
- ///
- public class GetFeedbackForDashboardPageResult
- {
- ///
- /// Emails to all users that are waiting on status updates.
- ///
- public List Emails { get; set; }
-
- ///
- /// Items on the requested page.
- ///
- public GetFeedbackForDashboardPageResultItem[] Items { get; set; }
-
- ///
- /// Total number of feedback entries
- ///
- public int TotalCount { get; set; }
- }
+using System.Collections.Generic;
+
+namespace Coderr.Server.Api.Web.Feedback.Queries
+{
+ ///
+ /// Result for
+ ///
+ public class GetFeedbackForDashboardPageResult
+ {
+ ///
+ /// Emails to all users that are waiting on status updates.
+ ///
+ public List Emails { get; set; }
+
+ ///
+ /// Items on the requested page.
+ ///
+ public GetFeedbackForDashboardPageResultItem[] Items { get; set; }
+
+ ///
+ /// Total number of feedback entries
+ ///
+ public int TotalCount { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Web/Feedback/Queries/GetFeedbackForDashboardPageResultItem.cs b/src/Server/Coderr.Server.Api/Web/Feedback/Queries/GetFeedbackForDashboardPageResultItem.cs
similarity index 92%
rename from src/Server/OneTrueError.Api/Web/Feedback/Queries/GetFeedbackForDashboardPageResultItem.cs
rename to src/Server/Coderr.Server.Api/Web/Feedback/Queries/GetFeedbackForDashboardPageResultItem.cs
index 73a0f331..b3d3914a 100644
--- a/src/Server/OneTrueError.Api/Web/Feedback/Queries/GetFeedbackForDashboardPageResultItem.cs
+++ b/src/Server/Coderr.Server.Api/Web/Feedback/Queries/GetFeedbackForDashboardPageResultItem.cs
@@ -1,36 +1,36 @@
-using System;
-
-namespace OneTrueError.Api.Web.Feedback.Queries
-{
- ///
- /// Result item for
- ///
- public class GetFeedbackForDashboardPageResultItem
- {
- ///
- /// Application that the feedback was written for
- ///
- public int ApplicationId { get; set; }
-
- ///
- /// Name of the application.
- ///
- public string ApplicationName { get; set; }
-
- ///
- /// Email adress to the user (if the user want to get status updates for the incident)
- ///
- public string EmailAddress { get; set; }
-
-
- ///
- /// Error description written by the user that experienced the error.
- ///
- public string Message { get; set; }
-
- ///
- /// When the user wrote the feedback
- ///
- public DateTime WrittenAtUtc { get; set; }
- }
+using System;
+
+namespace Coderr.Server.Api.Web.Feedback.Queries
+{
+ ///
+ /// Result item for
+ ///
+ public class GetFeedbackForDashboardPageResultItem
+ {
+ ///
+ /// Application that the feedback was written for
+ ///
+ public int ApplicationId { get; set; }
+
+ ///
+ /// Name of the application.
+ ///
+ public string ApplicationName { get; set; }
+
+ ///
+ /// Email adress to the user (if the user want to get status updates for the incident)
+ ///
+ public string EmailAddress { get; set; }
+
+
+ ///
+ /// Error description written by the user that experienced the error.
+ ///
+ public string Message { get; set; }
+
+ ///
+ /// When the user wrote the feedback
+ ///
+ public DateTime WrittenAtUtc { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Web/Feedback/Queries/GetIncidentFeedback.cs b/src/Server/Coderr.Server.Api/Web/Feedback/Queries/GetIncidentFeedback.cs
similarity index 92%
rename from src/Server/OneTrueError.Api/Web/Feedback/Queries/GetIncidentFeedback.cs
rename to src/Server/Coderr.Server.Api/Web/Feedback/Queries/GetIncidentFeedback.cs
index b33c8607..662e4b18 100644
--- a/src/Server/OneTrueError.Api/Web/Feedback/Queries/GetIncidentFeedback.cs
+++ b/src/Server/Coderr.Server.Api/Web/Feedback/Queries/GetIncidentFeedback.cs
@@ -1,30 +1,31 @@
-using System;
-using DotNetCqs;
-
-namespace OneTrueError.Api.Web.Feedback.Queries
-{
- ///
- /// Lists all feedback which has been made for an incident
- ///
- ///
- /// Will only fetch for the most specific id
- ///
- public class GetIncidentFeedback : Query
- {
- ///
- /// Creates a new instance of .
- ///
- /// Incident to get feedback for
- /// incidentId
- public GetIncidentFeedback(int incidentId)
- {
- if (incidentId <= 0) throw new ArgumentOutOfRangeException("incidentId");
- IncidentId = incidentId;
- }
-
- ///
- /// Incident to get feedback for
- ///
- public int IncidentId { get; private set; }
- }
+using System;
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Web.Feedback.Queries
+{
+ ///
+ /// Lists all feedback which has been made for an incident
+ ///
+ ///
+ /// Will only fetch for the most specific id
+ ///
+ [Message]
+ public class GetIncidentFeedback : Query
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// Incident to get feedback for
+ /// incidentId
+ public GetIncidentFeedback(int incidentId)
+ {
+ if (incidentId <= 0) throw new ArgumentOutOfRangeException("incidentId");
+ IncidentId = incidentId;
+ }
+
+ ///
+ /// Incident to get feedback for
+ ///
+ public int IncidentId { get; private set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Web/Feedback/Queries/GetIncidentFeedbackResult.cs b/src/Server/Coderr.Server.Api/Web/Feedback/Queries/GetIncidentFeedbackResult.cs
similarity index 94%
rename from src/Server/OneTrueError.Api/Web/Feedback/Queries/GetIncidentFeedbackResult.cs
rename to src/Server/Coderr.Server.Api/Web/Feedback/Queries/GetIncidentFeedbackResult.cs
index 6e492e48..ccd36901 100644
--- a/src/Server/OneTrueError.Api/Web/Feedback/Queries/GetIncidentFeedbackResult.cs
+++ b/src/Server/Coderr.Server.Api/Web/Feedback/Queries/GetIncidentFeedbackResult.cs
@@ -1,43 +1,43 @@
-using System;
-using System.Collections.Generic;
-
-namespace OneTrueError.Api.Web.Feedback.Queries
-{
- ///
- /// Result for .
- ///
- public class GetIncidentFeedbackResult
- {
- ///
- /// Creates a new instance of .
- ///
- /// Feedback items
- /// Emails to all users that are waiting on status updates.
- ///
- public GetIncidentFeedbackResult(IReadOnlyList items, ICollection emails)
- {
- if (items == null) throw new ArgumentNullException("items");
- if (emails == null) throw new ArgumentNullException("emails");
- Items = items;
- Emails = emails;
- }
-
- ///
- /// Serialization constructor
- ///
- protected GetIncidentFeedbackResult()
- {
- Emails = new List();
- }
-
- ///
- /// Emails to all users that are waiting on status updates.
- ///
- public ICollection Emails { get; set; }
-
- ///
- /// Items
- ///
- public IReadOnlyList Items { get; private set; }
- }
+using System;
+using System.Collections.Generic;
+
+namespace Coderr.Server.Api.Web.Feedback.Queries
+{
+ ///
+ /// Result for .
+ ///
+ public class GetIncidentFeedbackResult
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// Feedback items
+ /// Emails to all users that are waiting on status updates.
+ ///
+ public GetIncidentFeedbackResult(IReadOnlyList items, ICollection emails)
+ {
+ if (items == null) throw new ArgumentNullException("items");
+ if (emails == null) throw new ArgumentNullException("emails");
+ Items = items;
+ Emails = emails;
+ }
+
+ ///
+ /// Serialization constructor
+ ///
+ protected GetIncidentFeedbackResult()
+ {
+ Emails = new List();
+ }
+
+ ///
+ /// Emails to all users that are waiting on status updates.
+ ///
+ public ICollection Emails { get; set; }
+
+ ///
+ /// Items
+ ///
+ public IReadOnlyList Items { get; private set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Web/Feedback/Queries/GetIncidentFeedbackResultItem.cs b/src/Server/Coderr.Server.Api/Web/Feedback/Queries/GetIncidentFeedbackResultItem.cs
similarity index 89%
rename from src/Server/OneTrueError.Api/Web/Feedback/Queries/GetIncidentFeedbackResultItem.cs
rename to src/Server/Coderr.Server.Api/Web/Feedback/Queries/GetIncidentFeedbackResultItem.cs
index a9b562c7..4f9178fa 100644
--- a/src/Server/OneTrueError.Api/Web/Feedback/Queries/GetIncidentFeedbackResultItem.cs
+++ b/src/Server/Coderr.Server.Api/Web/Feedback/Queries/GetIncidentFeedbackResultItem.cs
@@ -1,25 +1,25 @@
-using System;
-
-namespace OneTrueError.Api.Web.Feedback.Queries
-{
- ///
- /// Result item for .
- ///
- public class GetIncidentFeedbackResultItem
- {
- ///
- /// Email if user can be contacted.
- ///
- public string EmailAddress { get; set; }
-
- ///
- /// Error description written by the user that experienced the error
- ///
- public string Message { get; set; }
-
- ///
- /// When the feedback was written
- ///
- public DateTime WrittenAtUtc { get; set; }
- }
+using System;
+
+namespace Coderr.Server.Api.Web.Feedback.Queries
+{
+ ///
+ /// Result item for .
+ ///
+ public class GetIncidentFeedbackResultItem
+ {
+ ///
+ /// Email if user can be contacted.
+ ///
+ public string EmailAddress { get; set; }
+
+ ///
+ /// Error description written by the user that experienced the error
+ ///
+ public string Message { get; set; }
+
+ ///
+ /// When the feedback was written
+ ///
+ public DateTime WrittenAtUtc { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Web/Overview/Queries/GetOverview.cs b/src/Server/Coderr.Server.Api/Web/Overview/Queries/GetOverview.cs
new file mode 100644
index 00000000..40628740
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Web/Overview/Queries/GetOverview.cs
@@ -0,0 +1,30 @@
+using DotNetCqs;
+
+namespace Coderr.Server.Api.Web.Overview.Queries
+{
+ ///
+ /// Get an Coderr summary (typically shown in the chart and right panel summary)
+ ///
+ [Message]
+ public class GetOverview : Query
+ {
+ ///
+ /// Amount of time to look back (i.e. startdate = DateTime.Now.Substract(WindowSize))
+ ///
+ ///
+ /// 1 = switch to hours
+ ///
+ public int NumberOfDays { get; set; }
+
+
+ ///
+ /// Load chart data.
+ ///
+ public bool IncludeChartData { get; set; } = true;
+
+ ///
+ /// Include summary count per partition.
+ ///
+ public bool IncludePartitions { get; set; } = false;
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.Api/Web/Overview/Queries/GetOverviewApplicationResult.cs b/src/Server/Coderr.Server.Api/Web/Overview/Queries/GetOverviewApplicationResult.cs
similarity index 95%
rename from src/Server/OneTrueError.Api/Web/Overview/Queries/GetOverviewApplicationResult.cs
rename to src/Server/Coderr.Server.Api/Web/Overview/Queries/GetOverviewApplicationResult.cs
index a050e065..f9978c7d 100644
--- a/src/Server/OneTrueError.Api/Web/Overview/Queries/GetOverviewApplicationResult.cs
+++ b/src/Server/Coderr.Server.Api/Web/Overview/Queries/GetOverviewApplicationResult.cs
@@ -1,81 +1,81 @@
-using System;
-using System.Collections.Generic;
-
-namespace OneTrueError.Api.Web.Overview.Queries
-{
- ///
- /// Application specific result for
- ///
- public class GetOverviewApplicationResult
- {
- private readonly Dictionary _index = new Dictionary();
-
- ///
- /// Creates a new instance of .
- ///
- /// Application name
- /// first day in sequence
- /// Number of days that this result contains
- /// label
- /// days
- public GetOverviewApplicationResult(string label, DateTime startDate, int days)
- {
- if (label == null) throw new ArgumentNullException("label");
- if (days < 1) throw new ArgumentOutOfRangeException("days");
-
- Label = label;
- if (days == 1)
- {
- var startTime = DateTime.Today.AddHours(DateTime.Now.Hour).AddHours(-22);
- for (var i = 0; i < 24; i++)
- {
- _index[startTime.AddHours(i)] = i;
- }
- Values = new int[24];
- }
- else
- {
- for (var i = 0; i < days; i++)
- {
- _index[startDate.AddDays(i)] = i;
- }
- Values = new int[days];
- }
- }
-
- ///
- /// Serialization constructor
- ///
- protected GetOverviewApplicationResult()
- {
- }
-
- ///
- /// Label
- ///
- public string Label { get; set; }
-
- ///
- /// Values, one per day
- ///
- public int[] Values { get; set; }
-
- ///
- /// Add another value
- ///
- /// Date
- /// Value
- /// value < 0
- public void AddValue(DateTime date, int value)
- {
- if (value < 0) throw new ArgumentOutOfRangeException("value");
-
- //future date = malconfigured reporting clients.
- if (!_index.ContainsKey(date))
- return;
-
- var indexPos = _index[date];
- Values[indexPos] = value;
- }
- }
+using System;
+using System.Collections.Generic;
+
+namespace Coderr.Server.Api.Web.Overview.Queries
+{
+ ///
+ /// Application specific result for
+ ///
+ public class GetOverviewApplicationResult
+ {
+ private readonly Dictionary _index = new Dictionary();
+
+ ///
+ /// Creates a new instance of .
+ ///
+ /// Application name
+ /// first day in sequence
+ /// Number of days that this result contains
+ /// label
+ /// days
+ public GetOverviewApplicationResult(string label, DateTime startDate, int days)
+ {
+ if (label == null) throw new ArgumentNullException("label");
+ if (days < 1) throw new ArgumentOutOfRangeException("days");
+
+ Label = label;
+ if (days == 1)
+ {
+ var startTime = DateTime.Today.AddHours(DateTime.Now.Hour).AddHours(-22);
+ for (var i = 0; i < 24; i++)
+ {
+ _index[startTime.AddHours(i)] = i;
+ }
+ Values = new int[24];
+ }
+ else
+ {
+ for (var i = 0; i < days; i++)
+ {
+ _index[startDate.AddDays(i)] = i;
+ }
+ Values = new int[days];
+ }
+ }
+
+ ///
+ /// Serialization constructor
+ ///
+ protected GetOverviewApplicationResult()
+ {
+ }
+
+ ///
+ /// Label
+ ///
+ public string Label { get; set; }
+
+ ///
+ /// Values, one per day
+ ///
+ public int[] Values { get; set; }
+
+ ///
+ /// Add another value
+ ///
+ /// Date
+ /// Value
+ /// value < 0
+ public void AddValue(DateTime date, int value)
+ {
+ if (value < 0) throw new ArgumentOutOfRangeException("value");
+
+ //future date = malconfigured reporting clients.
+ if (!_index.ContainsKey(date))
+ return;
+
+ var indexPos = _index[date];
+ Values[indexPos] = value;
+ }
+ }
}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Web/Overview/Queries/GetOverviewResult.cs b/src/Server/Coderr.Server.Api/Web/Overview/Queries/GetOverviewResult.cs
new file mode 100644
index 00000000..031862ca
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Web/Overview/Queries/GetOverviewResult.cs
@@ -0,0 +1,40 @@
+namespace Coderr.Server.Api.Web.Overview.Queries
+{
+ ///
+ /// Result for .
+ ///
+ public class GetOverviewResult
+ {
+ public GetOverviewResult()
+ {
+ IncidentsPerApplication = new GetOverviewApplicationResult[0];
+ TimeAxisLabels = new string[0];
+ StatSummary = new OverviewStatSummary { };
+ }
+
+ ///
+ /// 1 = switch to hours for incidents and reports.
+ ///
+ public int Days { get; set; }
+
+ ///
+ /// One collection per application
+ ///
+ public GetOverviewApplicationResult[] IncidentsPerApplication { get; set; }
+
+ ///
+ /// Aggregated summary
+ ///
+ public OverviewStatSummary StatSummary { get; set; }
+
+ ///
+ /// Labels for the time axis (X-axis) in the chart.
+ ///
+ public string[] TimeAxisLabels { get; set; }
+
+ ///
+ /// Number of reports that
+ ///
+ public int MissedReports { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Web/Overview/Queries/OverviewStatSummary.cs b/src/Server/Coderr.Server.Api/Web/Overview/Queries/OverviewStatSummary.cs
new file mode 100644
index 00000000..e36696ad
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Web/Overview/Queries/OverviewStatSummary.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Collections.Generic;
+
+namespace Coderr.Server.Api.Web.Overview.Queries
+{
+ ///
+ /// Stats for the last X days, part of .
+ ///
+ public class OverviewStatSummary
+ {
+ ///
+ /// Number of followers
+ ///
+ public int Followers { get; set; }
+
+ ///
+ /// Number of incidents
+ ///
+ public int Incidents { get; set; }
+
+ ///
+ /// Number of reports received
+ ///
+ public int Reports { get; set; }
+
+ ///
+ /// Number user feedback items
+ ///
+ public int UserFeedback { get; set; }
+
+ public DateTime? NewestIncidentReceivedAtUtc { get; set; }
+
+ public DateTime? NewestReportReceivedAtUtc { get; set; }
+
+ ///
+ /// Summary per partition
+ ///
+ public PartitionOverview[] Partitions { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.Api/Web/Overview/Queries/PartitionOverview.cs b/src/Server/Coderr.Server.Api/Web/Overview/Queries/PartitionOverview.cs
new file mode 100644
index 00000000..ed401962
--- /dev/null
+++ b/src/Server/Coderr.Server.Api/Web/Overview/Queries/PartitionOverview.cs
@@ -0,0 +1,23 @@
+namespace Coderr.Server.Api.Web.Overview.Queries
+{
+ ///
+ /// Summary for a partition
+ ///
+ public class PartitionOverview
+ {
+ ///
+ /// Name, used when reporting errors.
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// Name to show for users.
+ ///
+ public string DisplayName { get; set; }
+
+ ///
+ /// Amount of unique values for this partition.
+ ///
+ public int Value { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.App.Tests/App.config b/src/Server/Coderr.Server.App.Tests/App.config
similarity index 100%
rename from src/Server/OneTrueError.App.Tests/App.config
rename to src/Server/Coderr.Server.App.Tests/App.config
diff --git a/src/Server/Coderr.Server.App.Tests/Coderr.Server.App.Tests.csproj b/src/Server/Coderr.Server.App.Tests/Coderr.Server.App.Tests.csproj
new file mode 100644
index 00000000..0ab70ef6
--- /dev/null
+++ b/src/Server/Coderr.Server.App.Tests/Coderr.Server.App.Tests.csproj
@@ -0,0 +1,29 @@
+
+
+ netcoreapp3.1
+ Coderr.Server.App.Tests
+ Coderr.Server.App.Tests
+ Debug;Release;Premise
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.App.Tests/ConfigWrapper.cs b/src/Server/Coderr.Server.App.Tests/ConfigWrapper.cs
new file mode 100644
index 00000000..0406fb70
--- /dev/null
+++ b/src/Server/Coderr.Server.App.Tests/ConfigWrapper.cs
@@ -0,0 +1,33 @@
+using System.Collections.Generic;
+using Coderr.Server.Abstractions.Config;
+
+namespace Coderr.Server.App.Tests
+{
+ public class ConfigWrapper : IConfiguration
+ where TConfigType : IConfigurationSection, new()
+ {
+ private readonly ConfigurationStore _configurationStore;
+ private TConfigType _value;
+
+ public ConfigWrapper(ConfigurationStore configurationStore)
+ {
+ _configurationStore = configurationStore;
+ }
+
+ public TConfigType Value
+ {
+ get
+ {
+ if (EqualityComparer.Default.Equals(_value, default(TConfigType)))
+ _value = _configurationStore.Load();
+
+ return _value;
+ }
+ }
+
+ public void Save()
+ {
+ _configurationStore.Store(Value);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.App.Tests/Configuration/ConfigurationCategoryExtensionsTests.cs b/src/Server/Coderr.Server.App.Tests/Configuration/ConfigurationCategoryExtensionsTests.cs
similarity index 80%
rename from src/Server/OneTrueError.App.Tests/Configuration/ConfigurationCategoryExtensionsTests.cs
rename to src/Server/Coderr.Server.App.Tests/Configuration/ConfigurationCategoryExtensionsTests.cs
index ffc5d7d9..d071ca56 100644
--- a/src/Server/OneTrueError.App.Tests/Configuration/ConfigurationCategoryExtensionsTests.cs
+++ b/src/Server/Coderr.Server.App.Tests/Configuration/ConfigurationCategoryExtensionsTests.cs
@@ -1,62 +1,62 @@
-using System.Globalization;
-using System.Threading;
-using FluentAssertions;
-using OneTrueError.App.Tests.Configuration.TestEntitites;
-using OneTrueError.Infrastructure.Configuration;
-using Xunit;
-
-namespace OneTrueError.App.Tests.Configuration
-{
- public class ConfigurationCategoryExtensionsTests
- {
- [Fact]
- public void do_not_persist_category_name_as_its_just_metadata_and_part_of_the_key()
- {
- var cat = new SoCultural();
- cat.Number = 43.32f;
-
- Thread.CurrentThread.CurrentCulture = new CultureInfo("sv-se");
- var dict = cat.ToConfigDictionary();
-
- dict.Keys.Should().NotContain("SectionName");
- }
-
- [Fact]
- public void should_be_able_to_work_despite_local_culture_when_persisting_configuration()
- {
- var cat = new SoCultural();
- cat.Number = 43.32f;
-
- Thread.CurrentThread.CurrentCulture = new CultureInfo("sv-se");
- var dict = cat.ToConfigDictionary();
-
- dict["Number"].Should().Be("43.32");
- 43.32f.ToString()
- .Should()
- .Be("43,32", "because we need to validate changes when another culture is active.");
- }
-
- [Fact]
- public void should_format_values_with_invariant_culture()
- {
- var cat = new SoCultural();
- cat.Number = 43.32f;
-
- Thread.CurrentThread.CurrentCulture = new CultureInfo("sv-se");
- var dict = cat.ToConfigDictionary();
-
- dict["Number"].Should().Be("43.32");
- 43.32f.ToString().Should().Be("43,32", "because we need to validate that the config is correct.");
- }
-
- [Fact]
- public void should_ignore_categoryName_when_generating_The_dictionary()
- {
- var cat = new WriteTestSection();
-
- var dict = cat.ToConfigDictionary();
-
- dict.Keys.Should().NotContain(x => x == "SectionName");
- }
- }
+using System.Globalization;
+using System.Threading;
+using Coderr.Server.Abstractions.Config;
+using Coderr.Server.App.Tests.Configuration.TestEntitites;
+using FluentAssertions;
+using Xunit;
+
+namespace Coderr.Server.App.Tests.Configuration
+{
+ public class ConfigurationCategoryExtensionsTests
+ {
+ [Fact]
+ public void do_not_persist_category_name_as_its_just_metadata_and_part_of_the_key()
+ {
+ var cat = new SoCultural();
+ cat.Number = 43.32f;
+
+ Thread.CurrentThread.CurrentCulture = new CultureInfo("sv-se");
+ var dict = cat.ToConfigDictionary();
+
+ dict.Keys.Should().NotContain("SectionName");
+ }
+
+ [Fact]
+ public void Should_be_able_to_work_despite_local_culture_when_persisting_configuration()
+ {
+ var cat = new SoCultural();
+ cat.Number = 43.32f;
+
+ Thread.CurrentThread.CurrentCulture = new CultureInfo("sv-se");
+ var dict = cat.ToConfigDictionary();
+
+ dict["Number"].Should().Be("43.32");
+ 43.32f.ToString()
+ .Should()
+ .Be("43,32", "because we need to validate changes when another culture is active.");
+ }
+
+ [Fact]
+ public void Should_format_values_with_invariant_culture()
+ {
+ var cat = new SoCultural();
+ cat.Number = 43.32f;
+
+ Thread.CurrentThread.CurrentCulture = new CultureInfo("sv-se");
+ var dict = cat.ToConfigDictionary();
+
+ dict["Number"].Should().Be("43.32");
+ 43.32f.ToString().Should().Be("43,32", "because we need to validate that the config is correct.");
+ }
+
+ [Fact]
+ public void Should_ignore_categoryName_when_generating_The_dictionary()
+ {
+ var cat = new WriteTestSection();
+
+ var dict = cat.ToConfigDictionary();
+
+ dict.Keys.Should().NotContain(x => x == "SectionName");
+ }
+ }
}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.App.Tests/Configuration/DictionaryExtensionsTests.cs b/src/Server/Coderr.Server.App.Tests/Configuration/DictionaryExtensionsTests.cs
new file mode 100644
index 00000000..4fda6036
--- /dev/null
+++ b/src/Server/Coderr.Server.App.Tests/Configuration/DictionaryExtensionsTests.cs
@@ -0,0 +1,105 @@
+using System;
+using System.Collections.Generic;
+using Coderr.Server.Infrastructure.Configuration;
+using FluentAssertions;
+using Xunit;
+
+namespace Coderr.Server.App.Tests.Configuration
+{
+ public class DictionaryExtensionsTests
+ {
+ #region strings
+
+ [Fact]
+ public void Should_return_value_if_given_key_exists()
+ {
+ var dict = new Dictionary {{"Name", "Vlue"}};
+
+ var actual = dict.GetString("Name");
+
+ actual.Should().Be("Vlue");
+ }
+
+ [Fact]
+ public void Should_return_default_Value_if_given_key_do_not_exist()
+ {
+ var dict = new Dictionary {{"Name", "Vlue"}};
+
+ var actual = dict.GetString("Supplier", "Santa");
+
+ actual.Should().Be("Santa");
+ }
+
+ #endregion
+
+ #region boolean
+
+ [Fact]
+ public void Should_include_key_name_if_item_do_not_exist()
+ {
+ var dict = new Dictionary {{"Usable", "Vlue"}};
+
+ Action actual = () => dict.GetBoolean("hey!", null);
+
+ actual.Should().Throw().Which.Message.Contains("hey!");
+ }
+
+ [Fact]
+ public void Should_convert_to_bolean_if_given_item_is_found()
+ {
+ var dict = new Dictionary {{"Usable", "True"}};
+
+ var actual = dict.GetBoolean("Usable");
+
+ actual.Should().BeTrue();
+ }
+
+
+ [Fact]
+ public void Should_include_value_if_item_is_not_convertable_to_boolean()
+ {
+ var dict = new Dictionary {{"Usable", "Vlue"}};
+
+ Action actual = () => dict.GetBoolean("Usable");
+
+ actual.Should().Throw().Which.Message.Contains("Vlue");
+ }
+
+ #endregion
+
+ #region integer
+
+ [Fact]
+ public void Should_include_key_name_if_int_item_do_not_exist()
+ {
+ var dict = new Dictionary {{"Length", "Vlue"}};
+
+ Action actual = () => dict.GetInteger("hey!", null);
+
+ actual.Should().Throw().Which.Message.Contains("hey!");
+ }
+
+ [Fact]
+ public void Should_convert_to_integer_if_given_item_is_found()
+ {
+ var dict = new Dictionary {{"Length", "1100"}};
+
+ var actual = dict.GetInteger("Length");
+
+ actual.Should().Be(1100);
+ }
+
+
+ [Fact]
+ public void Should_include_value_if_item_is_not_convertable_to_integer()
+ {
+ var dict = new Dictionary {{"Usable", "Vlue"}};
+
+ Action actual = () => dict.GetInteger("Usable");
+
+ actual.Should().Throw().Which.Message.Contains("Vlue");
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.App.Tests/Configuration/TestEntitites/MySection.cs b/src/Server/Coderr.Server.App.Tests/Configuration/TestEntitites/MySection.cs
similarity index 83%
rename from src/Server/OneTrueError.App.Tests/Configuration/TestEntitites/MySection.cs
rename to src/Server/Coderr.Server.App.Tests/Configuration/TestEntitites/MySection.cs
index 70ab7433..6c028d8f 100644
--- a/src/Server/OneTrueError.App.Tests/Configuration/TestEntitites/MySection.cs
+++ b/src/Server/Coderr.Server.App.Tests/Configuration/TestEntitites/MySection.cs
@@ -1,28 +1,28 @@
-using System.Collections.Generic;
-using FluentAssertions.Execution;
-using OneTrueError.Infrastructure.Configuration;
-
-namespace OneTrueError.App.Tests.Configuration.TestEntitites
-{
- internal class MySection : IConfigurationSection
- {
- public string Name { get; private set; }
-
- public string SectionName
- {
- get { return "DemoCategory"; }
- }
-
- public IDictionary ToDictionary()
- {
- return new Dictionary {{"Name", Name}};
- }
-
- public void Load(IDictionary settings)
- {
- Name = settings["Name"];
- if (settings.Count != 1)
- throw new AssertionFailedException("Expected only one setting.");
- }
- }
+using System.Collections.Generic;
+using Coderr.Server.Abstractions.Config;
+using FluentAssertions.Execution;
+
+namespace Coderr.Server.App.Tests.Configuration.TestEntitites
+{
+ internal class MySection : IConfigurationSection
+ {
+ public string Name { get; private set; }
+
+ public string SectionName
+ {
+ get { return "DemoCategory"; }
+ }
+
+ public IDictionary ToDictionary()
+ {
+ return new Dictionary {{"Name", Name}};
+ }
+
+ public void Load(IDictionary settings)
+ {
+ Name = settings["Name"];
+ if (settings.Count != 1)
+ throw new AssertionFailedException("Expected only one setting.");
+ }
+ }
}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.App.Tests/Configuration/TestEntitites/NonExistantSection.cs b/src/Server/Coderr.Server.App.Tests/Configuration/TestEntitites/NonExistantSection.cs
new file mode 100644
index 00000000..3303bc96
--- /dev/null
+++ b/src/Server/Coderr.Server.App.Tests/Configuration/TestEntitites/NonExistantSection.cs
@@ -0,0 +1,23 @@
+using System.Collections.Generic;
+using Coderr.Server.Abstractions.Config;
+using Coderr.Server.Infrastructure.Configuration;
+
+namespace Coderr.Server.App.Tests.Configuration.TestEntitites
+{
+ public class NonExistantSection : IConfigurationSection
+ {
+ public string SectionName
+ {
+ get { return "NpNp"; }
+ }
+
+ public IDictionary ToDictionary()
+ {
+ return this.ToConfigDictionary();
+ }
+
+ public void Load(IDictionary settings)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.App.Tests/Configuration/TestEntitites/SoCultural.cs b/src/Server/Coderr.Server.App.Tests/Configuration/TestEntitites/SoCultural.cs
new file mode 100644
index 00000000..61aec782
--- /dev/null
+++ b/src/Server/Coderr.Server.App.Tests/Configuration/TestEntitites/SoCultural.cs
@@ -0,0 +1,25 @@
+using System.Collections.Generic;
+using Coderr.Server.Abstractions.Config;
+using Coderr.Server.Infrastructure.Configuration;
+
+namespace Coderr.Server.App.Tests.Configuration.TestEntitites
+{
+ internal class SoCultural : IConfigurationSection
+ {
+ public float Number { get; set; }
+
+ public string SectionName
+ {
+ get { return "SoCultural"; }
+ }
+
+ public IDictionary ToDictionary()
+ {
+ return this.ToConfigDictionary();
+ }
+
+ public void Load(IDictionary settings)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.App.Tests/Configuration/TestEntitites/WriteTestSection.cs b/src/Server/Coderr.Server.App.Tests/Configuration/TestEntitites/WriteTestSection.cs
similarity index 81%
rename from src/Server/OneTrueError.App.Tests/Configuration/TestEntitites/WriteTestSection.cs
rename to src/Server/Coderr.Server.App.Tests/Configuration/TestEntitites/WriteTestSection.cs
index c8ea3b54..0063db9f 100644
--- a/src/Server/OneTrueError.App.Tests/Configuration/TestEntitites/WriteTestSection.cs
+++ b/src/Server/Coderr.Server.App.Tests/Configuration/TestEntitites/WriteTestSection.cs
@@ -1,30 +1,30 @@
-using System.Collections.Generic;
-using OneTrueError.Infrastructure.Configuration;
-
-namespace OneTrueError.App.Tests.Configuration.TestEntitites
-{
- internal class WriteTestSection : IConfigurationSection
- {
- public WriteTestSection()
- {
- Properties = new Dictionary();
- }
-
- public IDictionary Properties { get; private set; }
-
- public string SectionName
- {
- get { return "WriteTest"; }
- }
-
- public IDictionary ToDictionary()
- {
- return Properties;
- }
-
- public void Load(IDictionary settings)
- {
- Properties = settings;
- }
- }
+using System.Collections.Generic;
+using Coderr.Server.Abstractions.Config;
+
+namespace Coderr.Server.App.Tests.Configuration.TestEntitites
+{
+ internal class WriteTestSection : IConfigurationSection
+ {
+ public WriteTestSection()
+ {
+ Properties = new Dictionary();
+ }
+
+ public IDictionary Properties { get; private set; }
+
+ public string SectionName
+ {
+ get { return "WriteTest"; }
+ }
+
+ public IDictionary ToDictionary()
+ {
+ return Properties;
+ }
+
+ public void Load(IDictionary settings)
+ {
+ Properties = settings;
+ }
+ }
}
\ No newline at end of file
diff --git a/src/Server/OneTrueError.App.Tests/Core/Accounts/AccountTests.cs b/src/Server/Coderr.Server.App.Tests/Core/Accounts/AccountTests.cs
similarity index 77%
rename from src/Server/OneTrueError.App.Tests/Core/Accounts/AccountTests.cs
rename to src/Server/Coderr.Server.App.Tests/Core/Accounts/AccountTests.cs
index fb9a68e9..d8624980 100644
--- a/src/Server/OneTrueError.App.Tests/Core/Accounts/AccountTests.cs
+++ b/src/Server/Coderr.Server.App.Tests/Core/Accounts/AccountTests.cs
@@ -1,100 +1,100 @@
-using System;
-using System.Security.Authentication;
-using FluentAssertions;
-using OneTrueError.App.Core.Accounts;
-using Xunit;
-
-namespace OneTrueError.App.Tests.Core.Accounts
-{
- public class AccountTests
- {
- [Fact]
- public void should_be_able_to_activate_the_account()
- {
- var sut = new Account("arne", "kalle");
-
- sut.Activate();
- var actual = sut.Login("kalle");
-
- actual.Should().BeTrue();
- }
-
- [Fact]
- public void should_be_able_to_change_password()
- {
- var sut = new Account("arne", "kalle");
-
- sut.ChangePassword("new");
- var actual = sut.Login("new");
-
- actual.Should().BeTrue();
- }
-
- [Fact]
- public void should_be_able_to_validate_the_current_password_so_that_We_know_that_its_safe_to_change_it()
- {
- var sut = new Account("arne", "kalle");
-
- var actual = sut.ValidatePassword("kalle");
-
- actual.Should().BeTrue();
- }
-
- [Fact]
- public void should_fail_if_account_have_not_been_activated()
- {
- var sut = new Account("arne", "kalle");
-
- Action actual = () => sut.Login("ping");
-
- actual.ShouldThrow();
- }
-
- [Fact]
- public void
- should_generate_activation_key_when_reset_is_requested_so_that_the_user_can_activate_its_account_user_the_emailed_link
- ()
- {
- var sut = new Account("arne", "kalle");
- sut.Activate();
- sut.Login("ping");
- sut.Login("pong");
- try
- {
- sut.Login("ping");
- }
- catch
- {
- }
-
- sut.RequestPasswordReset();
-
- sut.ActivationKey.Should().NotBeNull();
- sut.AccountState.Should().Be(AccountState.ResetPassword);
- }
-
- [Fact]
- public void three_failed_login_attempts_should_lock_the_account()
- {
- var sut = new Account("arne", "kalle");
- sut.Activate();
-
- sut.Login("ping");
- sut.Login("pong");
- Action actual = () => sut.Login("ping");
-
- actual.ShouldThrow();
- sut.AccountState.Should().Be(AccountState.Locked);
- }
-
- [Fact]
- public void validate_should_not_accept_invalid_password()
- {
- var sut = new Account("arne", "kalle");
-
- var actual = sut.ValidatePassword("kall");
-
- actual.Should().BeFalse();
- }
- }
+using System;
+using System.Security.Authentication;
+using Coderr.Server.Domain.Core.Account;
+using FluentAssertions;
+using Xunit;
+
+namespace Coderr.Server.App.Tests.Core.Accounts
+{
+ public class AccountTests
+ {
+ [Fact]
+ public void Should_be_able_to_activate_the_account()
+ {
+ var sut = new Account("arne", "kalle");
+
+ sut.Activate();
+ var actual = sut.Login("kalle");
+
+ actual.Should().BeTrue();
+ }
+
+ [Fact]
+ public void Should_be_able_to_change_password()
+ {
+ var sut = new Account("arne", "kalle");
+
+ sut.ChangePassword("new");
+ var actual = sut.Login("new");
+
+ actual.Should().BeTrue();
+ }
+
+ [Fact]
+ public void Should_be_able_to_validate_the_current_password_so_that_We_know_that_its_safe_to_change_it()
+ {
+ var sut = new Account("arne", "kalle");
+
+ var actual = sut.ValidatePassword("kalle");
+
+ actual.Should().BeTrue();
+ }
+
+ [Fact]
+ public void Should_fail_if_account_have_not_been_activated()
+ {
+ var sut = new Account("arne", "kalle");
+
+ Action actual = () => sut.Login("ping");
+
+ actual.Should().Throw();
+ }
+
+ [Fact]
+ public void
+ Should_generate_activation_key_when_reset_is_requested_so_that_the_user_can_activate_its_account_user_the_emailed_link
+ ()
+ {
+ var sut = new Account("arne", "kalle");
+ sut.Activate();
+ sut.Login("ping");
+ sut.Login("pong");
+ try
+ {
+ sut.Login("ping");
+ }
+ catch
+ {
+ }
+
+ sut.RequestPasswordReset();
+
+ sut.ActivationKey.Should().NotBeNull();
+ sut.AccountState.Should().Be(AccountState.ResetPassword);
+ }
+
+ [Fact]
+ public void three_failed_login_attempts_should_lock_the_account()
+ {
+ var sut = new Account("arne", "kalle");
+ sut.Activate();
+
+ sut.Login("ping");
+ sut.Login("pong");
+ Action actual = () => sut.Login("ping");
+
+ actual.Should().Throw();
+ sut.AccountState.Should().Be(AccountState.Locked);
+ }
+
+ [Fact]
+ public void validate_should_not_accept_invalid_password()
+ {
+ var sut = new Account("arne", "kalle");
+
+ var actual = sut.ValidatePassword("kall");
+
+ actual.Should().BeFalse();
+ }
+ }
}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.App.Tests/Core/Accounts/CommandHandlers/RegisterAccountHandlerTests.cs b/src/Server/Coderr.Server.App.Tests/Core/Accounts/CommandHandlers/RegisterAccountHandlerTests.cs
new file mode 100644
index 00000000..88a71545
--- /dev/null
+++ b/src/Server/Coderr.Server.App.Tests/Core/Accounts/CommandHandlers/RegisterAccountHandlerTests.cs
@@ -0,0 +1,67 @@
+using System.Threading.Tasks;
+using Coderr.Server.Api.Core.Accounts.Commands;
+using Coderr.Server.Api.Core.Accounts.Events;
+using Coderr.Server.Api.Core.Messaging.Commands;
+using Coderr.Server.App.Core.Accounts.CommandHandlers;
+using Coderr.Server.Domain.Core.Account;
+using DotNetCqs;
+using FluentAssertions;
+using NSubstitute;
+using Xunit;
+
+namespace Coderr.Server.App.Tests.Core.Accounts.CommandHandlers
+{
+ public class RegisterAccountHandlerTests
+ {
+ [Fact]
+ public async Task Should_create_a_new_account()
+ {
+ var configStore = new TestStore();
+ var repos = Substitute.For();
+ var cmd = new RegisterAccount("rne", "yo", "some@Emal.com");
+ var context = Substitute.For();
+ repos.When(x => x.CreateAsync(Arg.Any()))
+ .Do(x => x.Arg().SetId(3));
+
+
+ var sut = new RegisterAccountHandler(repos, configStore);
+ await sut.HandleAsync(context, cmd);
+ await repos.Received().CreateAsync(Arg.Any());
+ }
+
+ [Fact]
+ public async Task Should_inform_the_rest_of_the_system_about_the_new_account()
+ {
+ var configStore = new TestStore();
+ var repos = Substitute.For();
+ var context = Substitute.For();
+ var cmd = new RegisterAccount("rne", "yo", "some@Emal.com");
+ repos.When(x => x.CreateAsync(Arg.Any()))
+ .Do(x => x.Arg().SetId(3));
+
+
+ var sut = new RegisterAccountHandler(repos, configStore);
+ await sut.HandleAsync(context, cmd);
+
+ await context.Received().SendAsync(Arg.Any());
+ context.Method("SendAsync").Arg().AccountId.Should().Be(3);
+ }
+
+ [Fact]
+ public async Task Should_send_activation_email()
+ {
+ var configStore = new TestStore();
+ var repos = Substitute.For();
+ var context = Substitute.For();
+ var cmd = new RegisterAccount("rne", "yo", "some@Emal.com");
+ repos.When(x => x.CreateAsync(Arg.Any()))
+ .Do(x => x.Arg().SetId(3));
+
+
+ var sut = new RegisterAccountHandler(repos, configStore);
+ await sut.HandleAsync(context, cmd);
+
+ await context.Received().SendAsync(Arg.Any());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.App.Tests/Core/ApiKeys/ApiKeyTests.cs b/src/Server/Coderr.Server.App.Tests/Core/ApiKeys/ApiKeyTests.cs
new file mode 100644
index 00000000..40925d1a
--- /dev/null
+++ b/src/Server/Coderr.Server.App.Tests/Core/ApiKeys/ApiKeyTests.cs
@@ -0,0 +1,24 @@
+using System.Linq;
+using Coderr.Server.Abstractions.Security;
+using Coderr.Server.App.Core.ApiKeys;
+using Coderr.Server.Infrastructure.Security;
+using FluentAssertions;
+using Xunit;
+
+namespace Coderr.Server.App.Tests.Core.ApiKeys
+{
+ public class ApiKeyTests
+ {
+ [Fact]
+ public void added_application_should_be_added_into_the_claim_list()
+ {
+ var sut = new ApiKey();
+
+ sut.Add(1);
+
+ var claim = sut.Claims.FirstOrDefault(x => x.Type == CoderrClaims.Application && x.Value == "1");
+ claim.Should().NotBeNull("because applications Should be represented as claims");
+ }
+
+ }
+}
diff --git a/src/Server/Coderr.Server.App.Tests/Core/Applications/Commands/InviteUserHandlerTests.cs b/src/Server/Coderr.Server.App.Tests/Core/Applications/Commands/InviteUserHandlerTests.cs
new file mode 100644
index 00000000..45ff80ea
--- /dev/null
+++ b/src/Server/Coderr.Server.App.Tests/Core/Applications/Commands/InviteUserHandlerTests.cs
@@ -0,0 +1,170 @@
+using System;
+using System.Collections.Generic;
+using System.Security;
+using System.Security.Claims;
+using System.Threading.Tasks;
+using Coderr.Server.Abstractions.Security;
+using Coderr.Server.Api.Core.Applications.Events;
+using Coderr.Server.Api.Core.Invitations.Commands;
+using Coderr.Server.Api.Core.Messaging.Commands;
+using Coderr.Server.App.Core.Invitations;
+using Coderr.Server.App.Core.Invitations.CommandHandlers;
+using Coderr.Server.Domain.Core.Applications;
+using Coderr.Server.Domain.Core.User;
+using Coderr.Server.Infrastructure.Configuration;
+using Coderr.Server.Infrastructure.Security;
+using DotNetCqs;
+using FluentAssertions;
+using NSubstitute;
+using Xunit;
+
+namespace Coderr.Server.App.Tests.Core.Applications.Commands
+{
+ public class InviteUserHandlerTests
+ {
+ private readonly IApplicationRepository _applicationRepository;
+ private readonly IInvitationRepository _invitationRepository;
+ private readonly InviteUserHandler _sut;
+ private readonly IUserRepository _userRepository;
+ private readonly IMessageContext _context;
+ private readonly TestStore _configStore;
+
+ public InviteUserHandlerTests()
+ {
+ _invitationRepository = Substitute.For();
+ _userRepository = Substitute.For();
+ _applicationRepository = Substitute.For();
+ _userRepository.GetUserAsync(1).Returns(new User(1, "First"));
+ _applicationRepository.GetByIdAsync(1).Returns(new Application(1, "MyApp"));
+ _context = Substitute.For();
+ _configStore = new TestStore();
+ _sut = new InviteUserHandler(_invitationRepository, _userRepository, _applicationRepository, new ConfigWrapper(_configStore));
+ }
+
+ [Fact]
+ public async Task Should_create_an_invite_for_a_new_user()
+ {
+ var cmd = new InviteUser(1, "jonas@gauffin.com") { UserId = 1 };
+ var members = new[] { new ApplicationTeamMember(1, 3, "karl") };
+ ApplicationTeamMember actual = null;
+ _applicationRepository.GetTeamMembersAsync(1).Returns(members);
+ _applicationRepository.WhenForAnyArgs(x => x.CreateAsync(Arg.Any()))
+ .Do(x => actual = x.Arg());
+ _context.Principal.Returns(CreateAdminPrincipal());
+
+ await _sut.HandleAsync(_context, cmd);
+
+ await _applicationRepository.Received().CreateAsync(Arg.Any());
+ actual.EmailAddress.Should().Be(cmd.EmailAddress);
+ actual.ApplicationId.Should().Be(cmd.ApplicationId);
+ actual.AddedAtUtc.Should().BeCloseTo(DateTime.UtcNow, TimeSpan.FromSeconds(1));
+ actual.AddedByName.Should().Be("First");
+ }
+
+ [Fact]
+ public async Task Regular_user_should_not_be_able_to_invite()
+ {
+ var cmd = new InviteUser(1, "jonas@gauffin.com") { UserId = 1 };
+ var members = new[] { new ApplicationTeamMember(1, 3, "karl") };
+ _applicationRepository.GetTeamMembersAsync(1).Returns(members);
+ _context.Principal.Returns(CreateUserPrincipal());
+
+ Func actual = async () => await _sut.HandleAsync(_context, cmd);
+
+ await actual.Should().ThrowAsync();
+ }
+
+ [Fact]
+ public async Task Sysadmin_should_be_able_To_invite_users()
+ {
+ var cmd = new InviteUser(1, "jonas@gauffin.com") { UserId = 1 };
+ var members = new[] { new ApplicationTeamMember(3, 3, "karl") };
+ _applicationRepository.GetTeamMembersAsync(1).Returns(members);
+ _context.Principal.Returns(CreateAdminPrincipal());
+
+ await _sut.HandleAsync(_context, cmd);
+
+ await _context.Received().SendAsync(Arg.Any());
+ }
+
+ [Fact]
+ public async Task Should_not_allow_invites_when_the_invited_user_already_have_an_account()
+ {
+ var cmd = new InviteUser(1, "jonas@gauffin.com") { UserId = 2 };
+ var members = new[] { new ApplicationTeamMember(1, 3, "karl") };
+ _userRepository.FindByEmailAsync(cmd.EmailAddress).Returns(new User(3, "existing"));
+ _applicationRepository.GetTeamMembersAsync(1).Returns(members);
+ _context.Principal.Returns(CreateAdminPrincipal());
+
+ await _sut.HandleAsync(_context, cmd);
+
+ await _applicationRepository.DidNotReceive().CreateAsync(Arg.Any());
+ }
+
+ [Fact]
+ public async Task Should_not_allow_invites_when_the_invited_user_already_have_an_pending_invite()
+ {
+ var cmd = new InviteUser(1, "jonas@gauffin.com") { UserId = 1 };
+ var members = new[] { new ApplicationTeamMember(1, cmd.EmailAddress) };
+ _applicationRepository.GetTeamMembersAsync(1).Returns(members);
+ _context.Principal.Returns(CreateAdminPrincipal());
+
+ await _sut.HandleAsync(_context, cmd);
+
+ await _applicationRepository.DidNotReceive().CreateAsync(Arg.Any());
+ }
+
+ [Fact]
+ public async Task Should_notify_the_system_of_the_invite()
+ {
+ var cmd = new InviteUser(1, "jonas@gauffin.com") { UserId = 1 };
+ var members = new[] { new ApplicationTeamMember(1, 3, "karl") };
+ ApplicationTeamMember actual = null;
+ _applicationRepository.GetTeamMembersAsync(1).Returns(members);
+ _applicationRepository.WhenForAnyArgs(x => x.CreateAsync(Arg.Any()))
+ .Do(x => actual = x.Arg());
+ _context.Principal.Returns(CreateAdminPrincipal());
+
+ await _sut.HandleAsync(_context, cmd);
+
+ await _applicationRepository.Received().CreateAsync(Arg.Any());
+ await _context.Received().SendAsync(Arg.Any());
+ }
+
+ [Fact]
+ public async Task Should_send_an_invitation_email()
+ {
+ var cmd = new InviteUser(1, "jonas@gauffin.com") { UserId = 1 };
+ var members = new[] { new ApplicationTeamMember(1, 3, "karl") };
+ ApplicationTeamMember actual = null;
+ _applicationRepository.GetTeamMembersAsync(1).Returns(members);
+ _applicationRepository.WhenForAnyArgs(x => x.CreateAsync(Arg.Any()))
+ .Do(x => actual = x.Arg());
+ _context.Principal.Returns(CreateAdminPrincipal());
+
+ await _sut.HandleAsync(_context, cmd);
+
+ await _context.Received().SendAsync(Arg.Any());
+ }
+
+ private ClaimsPrincipal CreateAdminPrincipal()
+ {
+ var claims = new List
+ {
+ new Claim(ClaimTypes.Role, CoderrRoles.SysAdmin),
+ new Claim(CoderrClaims.ApplicationAdmin, "1")
+ };
+ var identity = new ClaimsIdentity(claims, AuthenticationTypes.Default);
+ return new ClaimsPrincipal(identity);
+ }
+
+ private ClaimsPrincipal CreateUserPrincipal()
+ {
+ var claims = new List
+ {
+ };
+ var identity = new ClaimsIdentity(claims, AuthenticationTypes.Default);
+ return new ClaimsPrincipal(identity);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Server/Coderr.Server.App.Tests/Core/Invitations/Commands/InvitationServiceTests.cs b/src/Server/Coderr.Server.App.Tests/Core/Invitations/Commands/InvitationServiceTests.cs
new file mode 100644
index 00000000..69c9cc29
--- /dev/null
+++ b/src/Server/Coderr.Server.App.Tests/Core/Invitations/Commands/InvitationServiceTests.cs
@@ -0,0 +1,151 @@
+using System.Threading.Tasks;
+using Coderr.Server.Api.Core.Accounts.Events;
+using Coderr.Server.Api.Core.Accounts.Requests;
+using Coderr.Server.App.Core.Accounts;
+using Coderr.Server.App.Core.Invitations;
+using Coderr.Server.Domain.Core.Account;
+using Coderr.Server.Domain.Core.Applications;
+using DotNetCqs;
+using FluentAssertions;
+using NSubstitute;
+using Xunit;
+
+namespace Coderr.Server.App.Tests.Core.Invitations.Commands
+{
+ public class InvitationServiceTests
+ {
+ public InvitationServiceTests()
+ {
+ _repository = Substitute.For();
+ _accountRepository = Substitute.For();
+ _applicationRepository = Substitute.For();
+ _messageBus = Substitute.For();
+ _sut = new AccountService(_accountRepository, _messageBus, _applicationRepository, _repository);
+ _invitedAccount = new Account("arne", "1234");
+ _invitedAccount.SetId(InvitedAccountId);
+ _invitedAccount.SetVerifiedEmail("jonas@gauffin.com");
+ _accountRepository.GetByIdAsync(InvitedAccountId).Returns(_invitedAccount);
+ }
+
+ private readonly IInvitationRepository _repository;
+ private readonly IAccountRepository _accountRepository;
+ private readonly AccountService _sut;
+ private readonly IMessageBus _messageBus;
+ private readonly Account _invitedAccount;
+ private readonly IApplicationRepository _applicationRepository;
+ private const int InvitedAccountId = 999;
+
+ [Fact]
+ public async Task
+ Should_delete_invitation_when_its_accepted_to_prevent_creating_multiple_accounts_with_the_same_invitation_key()
+ {
+ var invitation = new Invitation("invited@test.com", "inviter");
+ var request =
+ new AcceptInvitation(InvitedAccountId, invitation.InvitationKey) {AcceptedEmail = "arne@gauffin.com"};
+ invitation.Add(1, "arne");
+ _repository.GetByInvitationKeyAsync(request.InvitationKey).Returns(invitation);
+ var principal = PrincipalHelper.Create(52, "arne");
+
+ var actual = await _sut.AcceptInvitation(principal, request);
+
+ actual.Should().NotBeNull();
+ }
+
+ [Fact]
+ public async Task Should_notify_system_of_the_accepted_invitation()
+ {
+ var invitation = new Invitation("invited@test.com", "inviter");
+ var request =
+ new AcceptInvitation(InvitedAccountId, invitation.InvitationKey) {AcceptedEmail = "arne@gauffin.com"};
+ invitation.Add(1, "arne");
+ _repository.GetByInvitationKeyAsync(request.InvitationKey).Returns(invitation);
+ var principal = PrincipalHelper.Create(52, "arne");
+
+ var actual = await _sut.AcceptInvitation(principal, request);
+
+ await _messageBus.Received().SendAsync(principal, Arg.Any());
+ var evt = _messageBus.Method("SendAsync").Arg();
+ evt.AcceptedEmailAddress.Should().Be(request.AcceptedEmail);
+ evt.AccountId.Should().Be(InvitedAccountId);
+ evt.ApplicationIds[0].Should().Be(1);
+ evt.UserName.Should().Be(_invitedAccount.UserName);
+ }
+
+ [Fact]
+ public async Task Should_create_an_Account_for_invites_to_new_users()
+ {
+ var invitation = new Invitation("invited@test.com", "inviter");
+ var request =
+ new AcceptInvitation("arne", "pass", invitation.InvitationKey) {AcceptedEmail = "arne@gauffin.com"};
+ invitation.Add(1, "arne");
+ _repository.GetByInvitationKeyAsync(request.InvitationKey).Returns(invitation);
+ _accountRepository
+ .WhenForAnyArgs(x => x.CreateAsync(null))
+ .Do(x => x.Arg().SetId(52));
+ var principal = PrincipalHelper.Create(52, "arne");
+
+
+ var actual = await _sut.AcceptInvitation(principal, request);
+
+ await _accountRepository.Received().CreateAsync(Arg.Any());
+ var evt = _messageBus.Method("SendAsync").Arg();
+ evt.AccountId.Should().Be(52);
+ }
+
+ [Fact]
+ public async Task
+ Should_publish_AccountRegistered_if_a_new_account_is_created_as_we_bypass_the_regular_account_registration_flow()
+ {
+ var invitation = new Invitation("invited@test.com", "inviter");
+ var request =
+ new AcceptInvitation("arne", "pass", invitation.InvitationKey) {AcceptedEmail = "arne@gauffin.com"};
+ invitation.Add(1, "arne");
+ _repository.GetByInvitationKeyAsync(request.InvitationKey).Returns(invitation);
+ _accountRepository
+ .WhenForAnyArgs(x => x.CreateAsync(null))
+ .Do(x => x.Arg().SetId(52));
+ var principal = PrincipalHelper.Create(52, "arne");
+
+
+ var actual = await _sut.AcceptInvitation(principal, request);
+
+ await _messageBus.Received().SendAsync(principal, Arg.Any