public async Task <IActionResult> Post([FromBody] IroncladClient model)
        {
            if (string.IsNullOrEmpty(model.Id))
            {
                return(this.BadRequest(new { Message = $"Cannot create a client without a client ID" }));
            }

            var accessTokenType = default(AccessTokenType);

            if (model.AccessTokenType != null && !Enum.TryParse(model.AccessTokenType, out accessTokenType))
            {
                return(this.BadRequest(new { Message = $"Access token type '{model.AccessTokenType}' does not exist" }));
            }

            var client = new IdentityServerClient {
                ClientId = model.Id
            };

            // optional properties
            client.ClientName    = model.Name ?? client.ClientName;
            client.ClientSecrets = model.Secret == null ? client.ClientSecrets : new HashSet <Secret> {
                new Secret(model.Secret.Sha256())
            };
            client.AllowedCorsOrigins          = model.AllowedCorsOrigins ?? client.AllowedCorsOrigins;
            client.RedirectUris                = model.RedirectUris ?? client.RedirectUris;
            client.PostLogoutRedirectUris      = model.PostLogoutRedirectUris ?? client.PostLogoutRedirectUris;
            client.AllowedScopes               = model.AllowedScopes ?? client.AllowedScopes;
            client.AccessTokenType             = model.AccessTokenType == null ? client.AccessTokenType : accessTokenType;
            client.AllowedGrantTypes           = model.AllowedGrantTypes ?? client.AllowedGrantTypes;
            client.AllowAccessTokensViaBrowser = model.AllowAccessTokensViaBrowser ?? client.AllowAccessTokensViaBrowser;
            client.AllowOfflineAccess          = model.AllowOfflineAccess ?? client.AllowOfflineAccess;
            client.RequireClientSecret         = model.RequireClientSecret ?? client.RequireClientSecret;
            client.RequirePkce    = model.RequirePkce ?? client.RequirePkce;
            client.RequireConsent = model.RequireConsent ?? client.RequireConsent;
            client.Enabled        = model.Enabled ?? client.Enabled;

            using (var session = this.store.LightweightSession())
            {
                if (session.Query <PostgresClient>().Any(document => document.ClientId == client.ClientId))
                {
                    return(this.StatusCode((int)HttpStatusCode.Conflict, new { Message = "Client already exists" }));
                }

                session.Insert(client.ToEntity());

                await session.SaveChangesAsync();
            }

            return(this.Created(new Uri(this.HttpContext.GetIdentityServerRelativeUrl("~/api/clients/" + model.Id)), null));
        }
        public async Task <IActionResult> Put(string clientId, [FromBody] IroncladClient model)
        {
            if (string.Equals(clientId, "auth_console", StringComparison.OrdinalIgnoreCase))
            {
                return(this.BadRequest(new { Message = $"Cannot modify the authorization console client" }));
            }

            using (var session = this.store.LightweightSession())
            {
                var document = await session.Query <PostgresClient>().SingleOrDefaultAsync(item => item.ClientId == clientId);

                if (document == null)
                {
                    return(this.NotFound(new { Message = $"Client '{clientId}' not found" }));
                }

                var accessTokenType = default(AccessTokenType);
                if (model.AccessTokenType != null && !Enum.TryParse(model.AccessTokenType, out accessTokenType))
                {
                    return(this.BadRequest(new { Message = $"Access token type '{model.AccessTokenType}' does not exist" }));
                }

                // NOTE (Cameron): Because of the mapping/conversion unknowns we rely upon the Postgres integration to perform that operation which is why we do this...
                var client = new IdentityServerClient
                {
                    AllowedCorsOrigins     = model.AllowedCorsOrigins,
                    RedirectUris           = model.RedirectUris,
                    PostLogoutRedirectUris = model.PostLogoutRedirectUris,
                    AllowedScopes          = model.AllowedScopes,
                    AllowedGrantTypes      = model.AllowedGrantTypes,
                };

                client.AccessTokenType = model.AccessTokenType == null ? client.AccessTokenType : accessTokenType;

                // NOTE (Cameron): If the secret is updated we want to add the new secret...
                if (!string.IsNullOrEmpty(model.Secret))
                {
                    client.ClientSecrets = new List <Secret> {
                        new Secret(model.Secret.Sha256())
                    };
                }

                var entity = client.ToEntity();

                // update properties (everything supported is an optional update eg. if null is passed we will not update)
                document.ClientName                  = model.Name ?? document.ClientName;
                document.AllowedCorsOrigins          = entity.AllowedCorsOrigins ?? document.AllowedCorsOrigins;
                document.RedirectUris                = entity.RedirectUris ?? document.RedirectUris;
                document.PostLogoutRedirectUris      = entity.PostLogoutRedirectUris ?? document.PostLogoutRedirectUris;
                document.AllowedScopes               = entity.AllowedScopes ?? document.AllowedScopes;
                document.AccessTokenType             = model.AccessTokenType == null ? document.AccessTokenType : entity.AccessTokenType;
                document.AllowedGrantTypes           = entity.AllowedGrantTypes ?? document.AllowedGrantTypes;
                document.AllowAccessTokensViaBrowser = model.AllowAccessTokensViaBrowser ?? document.AllowAccessTokensViaBrowser;
                document.AllowOfflineAccess          = model.AllowOfflineAccess ?? document.AllowOfflineAccess;
                document.RequireClientSecret         = model.RequireClientSecret ?? document.RequireClientSecret;
                document.RequirePkce                 = model.RequirePkce ?? document.RequirePkce;
                document.RequireConsent              = model.RequireConsent ?? document.RequireConsent;
                document.Enabled = model.Enabled ?? document.Enabled;

                if (!string.IsNullOrEmpty(model.Secret))
                {
                    document.ClientSecrets.Add(entity.ClientSecrets.First());
                }

                session.Update(document);

                await session.SaveChangesAsync();
            }

            return(this.Ok());
        }