public Task <ActionResult <List <ModuleContentView> > > SearchModules([FromQuery] string?name = null, [FromQuery] string?fields = "*")
    {
        return(MatchExceptions(async() =>
        {
            var userId = GetUserIdStrict();
            var values = new Dictionary <string, object> {
                { "type", InternalContentType.module },
            };

            var query = "contentType = @type and !notdeleted()";

            if (name != null)
            {
                query += " and name like @name";
                values.Add("name", name);
            }

            var modules = await CachedSearcher.SearchSingleType <ModuleContentView>(userId, new SearchRequest()
            {
                type = "content",
                fields = fields ?? "*",
                query = query
            }, values);

            foreach (var m in modules)
            {
                var loaded = modService.RefreshModule(m);
                m.subcommands = loaded.subcommands;
            }

            return modules;
        }));
    }
    public Task <ActionResult <ContentView> > PostByNameAsync([FromBody] ContentView module)
    {
        return(MatchExceptions(async() =>
        {
            RateLimit(RateWrite);
            //Go find by name first
            var userId = GetUserIdStrict();
            var existing = await CachedSearcher.GetModuleForSystemByNameAsync(module.name, userId);

            if (existing != null)
            {
                module.id = existing.id;
            }
            else
            {
                module.id = 0;
            }

            //Need to add this just in case they don't, since this is a SPECIFIC module endpoint
            module.contentType = InternalContentType.module;

            var result = await CachedWriter.WriteAsync(module, userId);
            modService.RefreshModule(result); //Make it ready immediately, just in case.
            return result;
        }));
    }
Пример #3
0
    public async Task <ActionResult <bool> > GetRawAsync([FromRoute] string hash)
    {
        try
        {
            var requester = GetUserId() ?? 0;
            var result    = await CachedSearcher.SearchSingleType <ContentView>(requester, new SearchRequest()
            {
                type   = nameof(RequestType.content),
                query  = "hash = @hash",
                fields = "id, text, hash, literalType, lastRevisionId"
            }, new Dictionary <string, object> {
                { "hash", hash }
            });

            if (result.Count == 0)
            {
                throw new NotFoundException($"No content found with hash {hash}");
            }

            var content = result.First();

            Response.Headers.Add("ETag", $"{hash}-{content.lastRevisionId}");
            Response.Headers.Add("Content-Type", content.literalType);

            return(Content(content.text)); //File(result.Item1, result.Item2);
        }
        catch (Exception ex)
        {
            return(await MatchExceptions(() =>
            {
                ExceptionDispatchInfo.Capture(ex).Throw();
                return Task.FromResult(true);
            }));
        }
    }
Пример #4
0
    public Task <ActionResult <bool> > SendPasswordRecovery([FromBody] string email)
    {
        return(MatchExceptions(async() =>
        {
            if (config.ConfirmationType == InstantConfirmation)
            {
                throw new RequestException("User account creation is instant, meaning there is no email system in place and no way to recover passwords!");
            }

            var userId = await userService.GetUserIdFromEmailAsync(email);
            var tempPassword = userService.GetTemporaryPassword(userId);
            var user = await CachedSearcher.GetById <UserView>(RequestType.user, userId);
            var utcExpire = tempPassword.ExpireDate.ToUniversalTime();

            if (config.ConfirmationType.StartsWith(RestrictedConfirmation))
            {
                var message = new EmailMessage();
                message.Recipients = GetRestrictedEmails();
                message.Title = $"User {user.username} is trying to recover their account";
                message.Body = $"User {user.username} is trying to recover their account using email {email} on {Request.Host}\n\nIf this looks acceptable, please send them " +
                               $"an email stating they have a ONE TIME USE temporary password that will last until {utcExpire} UTC ({StaticUtils.HumanTime(utcExpire - DateTime.UtcNow)}):\n\n{tempPassword.Key}";

                //TODO: language? Configuration? I don't know
                await emailer.SendEmailAsync(message);
            }
            else
            {
                //TODO: language? Configuration? I don't know
                await emailer.SendEmailAsync(new EmailMessage(email, "Account Recovery",
                                                              $"You can temporarily access your account on '{Request.Host}' for another {StaticUtils.HumanTime(utcExpire - DateTime.UtcNow)} using the ONE TIME USE temporary password:\n\n{tempPassword.Key}"));
            }

            return true;
        }));
    }
Пример #5
0
 public Task <ActionResult <UserView> > GetMe()
 {
     return(MatchExceptions(() =>
     {
         var uid = GetUserIdStrict();
         return CachedSearcher.GetById <UserView>(RequestType.user, uid, true);
     }));
 }
    public Task <ActionResult <RequestResponse> > RequestAsync([FromBody] SearchRequests search)
    {
        var sw = new Stopwatch();

        sw.Start();

        return(MatchExceptions(async() =>
        {
            var data = await CachedSearcher.Search(search, GetUserId() ?? 0);
            var result = services.mapper.Map <RequestResponse>(data);
            result.requestUser = GetUserId();
            sw.Stop();
            result.totalTime = sw.Elapsed.TotalMilliseconds;
            result.nonDbTime = result.totalTime - result.databaseTimes.Sum(x => x.Value);

            return result;
        }));
    }
Пример #7
0
    public Task <ActionResult <bool> > SendRegistrationCode([FromBody] string email)
    {
        return(MatchExceptions(async() =>
        {
            if (config.ConfirmationType == InstantConfirmation)
            {
                throw new RequestException("User account creation is instant, there is no registration code");
            }

            var userId = await userService.GetUserIdFromEmailAsync(email);
            var registrationCode = await userService.GetRegistrationKeyAsync(userId);
            var user = await CachedSearcher.GetById <UserView>(RequestType.user, userId);

            if (string.IsNullOrWhiteSpace(registrationCode))
            {
                throw new RequestException("Couldn't find registration code for this email! Probably already registered!");
            }

            if (config.ConfirmationType.StartsWith(RestrictedConfirmation))
            {
                var message = new EmailMessage();
                message.Recipients = GetRestrictedEmails();
                message.Title = $"User {user.username} would like to create an account";
                message.Body = $"User {user.username} is trying to create an account using email {email} on {Request.Host}\n\nIf this looks acceptable, please send them " +
                               $"an email with instructions on how to create an account, using registration code:\n\n{registrationCode}";

                //TODO: language? Configuration? I don't know
                await emailer.SendEmailAsync(message);
            }
            else
            {
                //TODO: language? Configuration? I don't know
                await emailer.SendEmailAsync(new EmailMessage(email, "Registration instructions",
                                                              $"Your registration code for '{Request.Host}' is:\n\n{registrationCode}"));
            }

            return true;
        }));
    }
Пример #8
0
    public Task <ActionResult <UserView> > Register([FromBody] UserCredentials credentials)
    {
        //Like all controllers, we want ALL of the work possible to be inside a service, not the controller.
        //A service which can be tested!
        return(MatchExceptions <UserView>(async() =>
        {
            if (!config.AccountCreationEnabled)
            {
                throw new ForbiddenException("We're sorry, account creation is disabled at this time");
            }

            var userId = await userService.CreateNewUser(credentials.username, credentials.password, credentials.email);
            var result = await CachedSearcher.GetById <UserView>(RequestType.user, userId);

            if (config.ConfirmationType == InstantConfirmation)
            {
                services.logger.LogDebug("Instant user account creation set, completing registration immediately");
                var token = await userService.CompleteRegistration(userId, await userService.GetRegistrationKeyAsync(userId));
                result.special = token;
            }

            return result;
        }));
    }
Пример #9
0
    protected async Task <UserView> GetUserViewStrictAsync()
    {
        var userId = GetUserIdStrict();

        return(await CachedSearcher.GetById <UserView>(RequestType.user, userId) ?? throw new RequestException($"Couldn't find user with id {userId}"));
    }