示例#1
0
        public static async Task AuthorizeUploadTus(AuthorizeContext arg)
        {
            CommonController.LogDebug("Authorizing upload request");
            var user = await UserSessions.GetLoggedInUser(arg.HttpContext);

            if (user != null)
            {
                var video = new Video
                {
                    id      = new Guid(arg.HttpContext.Request.Headers["guid"]),
                    userid  = user.userid,
                    privacy = VideoPrivacy.Processing,
                };

                CommonController.LogDebug("Video metadata:");
                CommonController.LogDebug($"\t id: {video.id}");
                CommonController.LogDebug($"\t userid: {video.userid}");
                CommonController.LogDebug($"\t privacy: {video.privacy}");


                var  cachedOwner = (User)uploadAuthorisationCache[video.id.ToString()];
                bool exists;
                bool owns;

                if (cachedOwner == null)
                {
                    CommonController.LogDebug("No owner found in cache");
                    using var connection = Database.OpenNewConnection();
                    exists = await VideoExists(video.id, connection);

                    owns = await UserOwnsVideo(video.id, user.userid, connection);
                    await AddOrUpdateVideo(video, connection);
                }
                //NOTE(Simon): At this point the video has definitely been created, so it exists and is owned by the cached user
                else if (cachedOwner.userid == user.userid)
                {
                    CommonController.LogDebug("User is owner of video. allow upload");
                    exists = true;
                    owns   = true;
                }
                else
                {
                    CommonController.LogDebug("User not authorized to update this video");
                    arg.FailRequest("This user is not authorized to update this video");
                    return;
                }

                if (exists && owns || !exists)
                {
                    CommonController.LogDebug("Adding user to cache");
                    uploadAuthorisationCache.Add(video.id.ToString(), user, new CacheItemPolicy {
                        SlidingExpiration = TimeSpan.FromMinutes(10)
                    });
                    return;
                }
            }

            arg.FailRequest("This user is not authorized to update this video");
            CommonController.LogDebug("User not authorized to upload videos");
        }
示例#2
0
        private static async Task DeleteVideoConfirmGet(HttpContext context)
        {
            CommonController.SetHTMLContentType(context);

            var userTask = UserSessions.GetLoggedInUser(context);

            using var connection = Database.OpenNewConnection();
            var user = await userTask;

            if (user != null && GuidHelpers.TryDecode(context.Request.Query["id"], out var videoId))
            {
                var video = await GetVideo(videoId, connection);

                if (UserOwnsVideo(video, user.userid))
                {
                    await DeleteVideo(video.id, connection);

                    context.Response.Redirect("/my_videos");
                }
                else
                {
                    await CommonController.Write404(context);
                }
            }
            else
            {
                await CommonController.Write404(context);
            }
        }
示例#3
0
        private static async Task EditVideoGet(HttpContext context)
        {
            CommonController.SetHTMLContentType(context);

            var userTask = UserSessions.GetLoggedInUser(context);

            using var connection = Database.OpenNewConnection();
            var user = await userTask;

            if (user != null && GuidHelpers.TryDecode(context.Request.Query["id"], out var videoId))
            {
                var video = await GetVideo(videoId, connection);

                if (UserOwnsVideo(video, user.userid))
                {
                    var templateContext = new TemplateContext(new { video });
                    await context.Response.WriteAsync(await HTMLRenderer.Render(context, "Templates\\editVideo.liquid", templateContext));
                }
                else
                {
                    await CommonController.Write404(context);
                }
            }
            else
            {
                await CommonController.Write404(context);
            }
        }
示例#4
0
        private static async Task MyVideosGet(HttpContext context)
        {
            CommonController.SetHTMLContentType(context);

            var userTask = UserSessions.GetLoggedInUser(context);

            using var connection = Database.OpenNewConnection();
            var user = await userTask;

            if (user != null)
            {
                const int countPerPage = 20;
                int       page         = 1;
                if (context.Request.Query.ContainsKey("page"))
                {
                    Int32.TryParse(context.Request.Query["page"], out page);
                }

                int offset = (page - 1) * countPerPage;

                var numVideos = await NumVideosForUser(user.userid, connection);

                var VideosTask = VideosForUser(user.userid, countPerPage, offset, connection);

                var pagination = new Pagination(numVideos, countPerPage, offset);

                var templateContext = new TemplateContext(new { videos = await VideosTask, pagination });

                await context.Response.WriteAsync(await HTMLRenderer.Render(context, "Templates\\myVideos.liquid", templateContext));
            }
            else
            {
                await CommonController.Write404(context);
            }
        }
示例#5
0
        private static async Task VideoGet(HttpContext context)
        {
            CommonController.SetHTMLContentType(context);

            if (GuidHelpers.TryDecode(context.Request.Query["id"], out var videoId))
            {
                using var connection = Database.OpenNewConnection();
                var video = await GetVideo(videoId, connection);

                var user = await UserSessions.GetLoggedInUser(context);

                if (video != null && UserCanViewVideo(video, user))
                {
                    bool userOwnsVideo = UserOwnsVideo(video, user.userid);
                    var  relatedVideos = new List <Video>();

                    var templateContext = new TemplateContext(new { video, relatedVideos, userOwnsVideo });
                    await context.Response.WriteAsync(await HTMLRenderer.Render(context, "Templates\\video.liquid", templateContext));
                    await AddVideoView(video.id, context, connection);
                }
                else
                {
                    await CommonController.Write404(context);
                }
            }
            else
            {
                await CommonController.Write404(context);
            }
        }
示例#6
0
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                CommonController.baseURL = "https://localhost:5001";
            }
            else
            {
                app.UseHsts();
                CommonController.baseURL = "https://vivista.net";
            }

            CommonController.wwwroot = env.WebRootPath;
            app.UseStaticFiles();
            app.UseTus(context =>
            {
                if (!context.Request.Path.StartsWithSegments(new PathString("/api/file")) || context.Request.Method == "GET")
                {
                    return(null);
                }
                var guid    = new Guid(context.Request.Headers["guid"]);
                string path = Path.Combine(VideoController.baseFilePath, guid.ToString());
                return(new DefaultTusConfiguration
                {
                    Store = new TusDiskStore(path),
                    UrlPath = "/api/file",
                    Events = new Events
                    {
                        OnAuthorizeAsync = VideoController.AuthorizeUploadTus,
                        OnBeforeCreateAsync = async createContext => Directory.CreateDirectory(path),
                        //NOTE(Simon): Do not allow deleting by someone trying to exploit the protocol
                        OnBeforeDeleteAsync = async deleteContext => deleteContext.FailRequest(""),
                        OnFileCompleteAsync = VideoController.ProcessUploadTus,
                    }
                });
            });

            //Task.Run(PeriodicFunction);

            app.Run(async(context) =>
            {
                var watch            = Stopwatch.StartNew();
                var authenticateTask = UserSessions.GetLoggedInUser(context);

                PrintDebugData(context);

                SetJSONContentType(context);

                await authenticateTask;
                watch.Stop();
                CommonController.LogDebug($"request preamble: {watch.Elapsed.TotalMilliseconds} ms");

                await router.RouteAsync(context.Request, context);
            });
        }
示例#7
0
        public static async Task <string> Render(HttpContext httpContext, string templateName, TemplateContext context, BaseLayout layout = BaseLayout.Web)
        {
            CommonController.LogDebug($"Begin Rendering {templateName}");
            var watch = Stopwatch.StartNew();

            if (templateCache.TryGetValue(templateName, out var template))
            {
                CommonController.LogDebug("Template found");
                var user = await UserSessions.GetLoggedInUser(httpContext);

                string result;

                if (context == null)
                {
                    context = new TemplateContext();
                    context.Options.MemberAccessStrategy = defaultAccessStrategy;
                    context.Options.Scope.SetValue("User", FluidValue.Create(user, context.Options));
                    AddDefaultFilters(context);

                    result = await template.RenderAsync();
                }
                else
                {
                    //NOTE(Simon): This lib requires users to register all used models by their type name.
                    //NOTE(cont.): This block prevents having to do it manually.
                    context.Options.MemberAccessStrategy = defaultAccessStrategy;
                    context.Options.Scope.SetValue("User", FluidValue.Create(user, context.Options));
                    AddDefaultFilters(context);

                    result = await template.RenderAsync(context);
                }

                if (layout != BaseLayout.None)
                {
                    var content = new TemplateContext(new { content = result });
                    context.Options.MemberAccessStrategy = defaultAccessStrategy;
                    content.Options.Scope.SetValue("User", FluidValue.Create(user, context.Options));
                    AddDefaultFilters(context);

                    result = await layoutCache[layout].RenderAsync(content);
                }

                watch.Stop();
                CommonController.LogDebug($"rendering: {watch.Elapsed.TotalMilliseconds} ms");

                return(result);
            }
            else
            {
                Console.WriteLine("Template not found");
                throw new Exception($"Something went wrong while rendering {templateName}");
            }
        }
        private static async Task LogoutGet(HttpContext context)
        {
            if (await UserSessions.GetLoggedInUser(context) != null)
            {
                using var connection = Database.OpenNewConnection();

                await UserSessions.InvalidateSession(context.Request.Cookies["session"], connection);

                context.Response.Cookies.Delete("session");

                context.Response.Redirect("/");
            }
        }
        private static async Task UpdatePasswordPost(HttpContext context)
        {
            SetHTMLContentType(context);

            string currentPassword      = context.Request.Form["current-password"];
            string password             = context.Request.Form["new-password"];
            string passwordConfirmation = context.Request.Form["password-confirmation"];

            var(success, result) = ValidatePassword(password, passwordConfirmation);

            if (!success)
            {
                var templateContext = new TemplateContext(new { success = false, message = result });
                await context.Response.WriteAsync(await HTMLRenderer.Render(context, "Templates\\settings.liquid", templateContext));
            }
            else
            {
                using var connection = Database.OpenNewConnection();
                var user = await UserSessions.GetLoggedInUser(context);

                var currentPassCorrect = await AuthenticateUser(user.email, currentPassword, connection);

                if (currentPassCorrect)
                {
                    if (await UpdatePassword(user.email, password, connection))
                    {
                        var templateContext = new TemplateContext(new { success = true, message = "" });
                        await context.Response.WriteAsync(await HTMLRenderer.Render(context, "Templates\\settings.liquid", templateContext));
                    }
                    else
                    {
                        var templateContext = new TemplateContext(new { success = false, message = "Something went wrong while updating password. Please try again later" });
                        await context.Response.WriteAsync(await HTMLRenderer.Render(context, "Templates\\settings.liquid", templateContext));
                    }
                }
                else
                {
                    var templateContext = new TemplateContext(new { success = false, message = "Current password is wrong" });
                    await context.Response.WriteAsync(await HTMLRenderer.Render(context, "Templates\\settings.liquid", templateContext));
                }
            }
        }
示例#10
0
        private static async Task EditVideoPost(HttpContext context)
        {
            CommonController.SetHTMLContentType(context);

            var userTask = UserSessions.GetLoggedInUser(context);

            using var connection = Database.OpenNewConnection();
            var user = await userTask;

            if (user != null && GuidHelpers.TryDecode(context.Request.Query["id"], out var videoId))
            {
                var video = await GetVideo(videoId, connection);

                if (UserOwnsVideo(video, user.userid))
                {
                    var form = context.Request.Form;
                    video.title       = form["title"];
                    video.description = form["description"];

                    //TODO(Simon): Deduplicate tags. Should be cleaned by frontend, but may be malicious data.
                    string[] tags             = form["tags"].ToString().Split(',');
                    var      deduplicatedTags = new HashSet <string>(tags);
                    video.tags = deduplicatedTags.ToList();
                    if (Int32.TryParse(form["privacy"], out var privacyInt))
                    {
                        video.privacy = (VideoPrivacy)privacyInt;
                    }

                    await AddOrUpdateVideo(video, connection);

                    context.Response.Redirect("/my_videos");
                }
                else
                {
                    await CommonController.Write404(context);
                }
            }
            else
            {
                await CommonController.Write404(context);
            }
        }
示例#11
0
        private static async Task UpdateVideoPrivacyPost(HttpContext context)
        {
            CommonController.SetHTMLContentType(context);

            var userTask = UserSessions.GetLoggedInUser(context);

            using var connection = Database.OpenNewConnection();
            var user = await userTask;

            if (user != null && GuidHelpers.TryDecode(context.Request.Query["id"], out var videoid))
            {
                var video = await GetVideo(videoid, connection);

                if (UserOwnsVideo(video, user.userid))
                {
                    if (Int32.TryParse(context.Request.Form["video-privacy"], out int privacy))
                    {
                        await SetVideoPrivacy(video.id, (VideoPrivacy)privacy, connection);
                    }
                }
            }

            context.Response.Redirect("/my_videos");
        }
示例#12
0
        private static async Task FinishUploadApi(HttpContext context)
        {
            var form = context.Request.Form;

            if (Guid.TryParse(form["id"], out var guid))
            {
                var userTask = UserSessions.GetLoggedInUser(context);

                using var connection = Database.OpenNewConnection();

                var user  = await userTask;
                var video = await GetVideo(guid, connection);

                if (user != null && await UserOwnsVideo(guid, user.userid, connection))
                {
                    var directoryPath = Path.Combine(baseFilePath, guid.ToString());
                    var videoPath     = Path.Combine(directoryPath, "main.mp4");
                    var thumbPath     = Path.Combine(directoryPath, "thumb.jpg");

                    var process = new Process();
                    process.StartInfo.UseShellExecute        = false;
                    process.StartInfo.RedirectStandardOutput = true;
                    process.StartInfo.RedirectStandardError  = true;

                    string ffmpegArgs = $"-hide_banner -loglevel error -y -ss 00:00:05 -i {videoPath} -frames:v 1 -q:v 3 -s 720x360 {thumbPath}";

                    if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
                    {
                        //process.StartInfo.FileName = @"\bin\ffmpeg.exe";
                        process.StartInfo.FileName  = "/usr/bin/ffmpeg";
                        process.StartInfo.Arguments = $"{ffmpegArgs}";
                        //process.StartInfo.Arguments = $"-c ffmpeg {ffmpegArgs}";
                        CommonController.LogDebug($"Running following command: {process.StartInfo.Arguments}");
                    }
                    else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                    {
                        process.StartInfo.FileName  = "cmd.exe";
                        process.StartInfo.Arguments = $"/C ffmpeg.exe {ffmpegArgs}";
                        CommonController.LogDebug($"Running following command: {process.StartInfo.Arguments}");
                    }

                    process.Start();

                    await process.WaitForExitAsync();

                    CommonController.LogDebug($"Ffmpeg exit code: {process.ExitCode}");
                    if (process.ExitCode == 0)
                    {
                        CommonController.LogDebug("Thumbnail generated succesfully");
                        video.privacy      = VideoPrivacy.Unlisted;
                        video.downloadsize = (int)GetDirectorySize(new DirectoryInfo(directoryPath));
                        video.length       = await FfmpegGetVideoLength(videoPath);

                        var meta = ReadMetaFile(Path.Combine(directoryPath, "meta.json"));

                        video.title       = meta.title;
                        video.description = meta.description;

                        CommonController.LogDebug($"Video Privacy: {video.privacy}");
                        CommonController.LogDebug($"Video Size: {video.downloadsize}");
                        CommonController.LogDebug($"Video length: {video.length}");

                        if (await AddOrUpdateVideo(video, connection))
                        {
                            CommonController.LogDebug("Database row updated succesfully");
                            await context.Response.WriteAsJsonAsync(new { success = true });

                            CleanPartialUploads(video.id);
                        }
                        else
                        {
                            Console.WriteLine("Error while updating database row for video");
                            await CommonController.WriteError(context, "{}", StatusCodes.Status500InternalServerError);
                        }
                    }
                    else
                    {
                        Console.WriteLine("Error while generating thumbnail");
                        Console.WriteLine($"\t {process.StandardOutput.ReadToEnd()}");
                        Console.WriteLine($"\t {process.StandardError.ReadToEnd()}");
                        await CommonController.WriteError(context, "{}", StatusCodes.Status500InternalServerError);
                    }
                }
                else
                {
                    CommonController.LogDebug("User does not own video");
                    await CommonController.WriteError(context, "{}", StatusCodes.Status401Unauthorized);
                }
            }
            else
            {
                await CommonController.WriteError(context, "{}", StatusCodes.Status400BadRequest);
            }
        }