public async Task <IActionResult> CompleteSignature([FromBody][Required] InProgressClaSignatureDTO request)
        {
            var session = await HttpContext.Request.Cookies.GetSession(database);

            if (session == null)
            {
                return(this.WorkingForbid("You don't have an active session"));
            }

            var signature = await database.InProgressClaSignatures.FirstOrDefaultAsync(s => s.SessionId == session.Id);

            if (signature == null)
            {
                return(NotFound());
            }

            if (!signatureStorage.Configured)
            {
                return(Problem("Remote storage for signed documents is not configured"));
            }

            if (!mailQueue.Configured)
            {
                return(Problem("Email on server is not configured"));
            }

            // Request must now have signer and guardian (if minor) signature fields set (all other changes are
            // ignored)
            if (string.IsNullOrWhiteSpace(request.SignerSignature) || request.SignerSignature.Length < 3)
            {
                return(BadRequest("Missing signature"));
            }

            if (!signature.SignerIsMinor.HasValue)
            {
                return(BadRequest("Is minor field is not filled in"));
            }

            if (signature.SignerIsMinor == true && (string.IsNullOrWhiteSpace(request.GuardianSignature) ||
                                                    request.GuardianSignature.Length < 3))
            {
                return(BadRequest("Missing guardian signature"));
            }

            // Verify that signature status is fine before moving onto accepting it
            if (!signature.EmailVerified || string.IsNullOrWhiteSpace(signature.Email))
            {
                return(BadRequest("Email is not verified"));
            }

            if (!signature.GithubSkipped && (string.IsNullOrWhiteSpace(signature.GithubAccount) ||
                                             string.IsNullOrEmpty(signature.GithubEmail) || !signature.GithubUserId.HasValue))
            {
                return(BadRequest("Bad Github account status in signature"));
            }

            if (signature.GithubSkipped && signature.GithubAccount != null)
            {
                return(BadRequest("Bad Github account status in signature"));
            }

            if (signature.DeveloperUsername != null && string.IsNullOrWhiteSpace(signature.DeveloperUsername))
            {
                return(BadRequest("Bad format username"));
            }

            if (signature.SignerIsMinor == true && (string.IsNullOrWhiteSpace(request.GuardianName) ||
                                                    request.GuardianName.Length < 3))
            {
                return(BadRequest("Missing guardian name"));
            }

            if (string.IsNullOrWhiteSpace(request.SignerName) || request.SignerName.Length < 3)
            {
                return(BadRequest("Missing signer name"));
            }

            // Load the CLA data (it must still be active, otherwise signing is not valid)
            var cla = await database.Clas.FindAsync(signature.ClaId);

            if (cla is not {
                Active : true
            })
        public async Task <IActionResult> UpdateSigningProgress([FromBody][Required] InProgressClaSignatureDTO request)
        {
            var session = await HttpContext.Request.Cookies.GetSession(database);

            if (session == null)
            {
                return(this.WorkingForbid("You don't have an active session"));
            }

            var signature = await database.InProgressClaSignatures.FirstOrDefaultAsync(s => s.SessionId == session.Id);

            if (signature == null)
            {
                return(NotFound());
            }

            // Update allowed fields from request to the data of the in-progress signature stored in the database
            bool changes = false;

            if (request.GithubSkipped != signature.GithubSkipped)
            {
                changes = true;
                signature.GithubSkipped = request.GithubSkipped;

                if (signature.GithubSkipped)
                {
                    signature.GithubAccount = null;
                    signature.GithubEmail   = null;
                    signature.GithubUserId  = null;
                }
            }

            if (request.DeveloperUsername != signature.DeveloperUsername)
            {
                changes = true;
                signature.DeveloperUsername = request.DeveloperUsername;

                if (string.IsNullOrWhiteSpace(signature.DeveloperUsername))
                {
                    signature.DeveloperUsername = null;
                }
            }

            if (request.GuardianName != signature.GuardianName)
            {
                changes = true;

                signature.GuardianName = request.GuardianName;
                if (string.IsNullOrWhiteSpace(signature.GuardianName))
                {
                    signature.GuardianName = null;
                }
            }

            if (request.SignerName != signature.SignerName)
            {
                changes = true;

                signature.SignerName = request.SignerName;
            }

            if (request.SignerIsMinor != signature.SignerIsMinor)
            {
                changes = true;

                signature.SignerIsMinor = request.SignerIsMinor;

                if (signature.SignerIsMinor != true)
                {
                    signature.GuardianName = null;
                }
            }

            if (changes)
            {
                signature.BumpUpdatedAt();
                await database.SaveChangesAsync();
            }

            return(Ok());
        }