Exemplo n.º 1
0
        public async Task DeleteFileAsync(string fileId)
        {
            AssertIdentityProvided(); // Quota is affected
            var filePath = GetTargetFilePath(fileId);
            var fileInfo = await Task.Run(() => new FileInfo(filePath));

            var fileSize = fileInfo.Length;
            await Task.Run(() => File.Delete(filePath));

            if (_owner != null)
            {
                var lockEntry = ServerContext.ServiceTable[_owner].UserLock;
                // Decrease user storage usage
                await lockEntry.ObtainExclusiveWriteAsync();

                var userManager = new WebUserManager(ServerContext);
                var ownerData   = await userManager.FindUserByUsernameAsync(_owner);

                var prevStorageUsage = ownerData.StorageUsage;
                ownerData.StorageUsage -= fileSize;
                await userManager.UpdateUserInDatabaseAsync(ownerData);

                lockEntry.ReleaseExclusiveWrite();
            }
        }
Exemplo n.º 2
0
        public async Task <FileUploadResult> HandleUploadAsync(string fileName, Stream stream)
        {
            AssertIdentityProvided(); // Quota is affected
            var fileId               = Guid.NewGuid().ToString();
            var targetFile           = GetTargetFilePath(fileId);
            var uploadStreamFileSize = stream.Length;

            try
            {
                // Write file (Wait for upload throttle)
                await ServerContext.ServiceTable[_owner]
                .UploadThrottle.WithResourceAsync(async() =>
                {
                    using (var destinationStream = File.Create(targetFile))
                    {
                        await stream.CopyToAsync(destinationStream);
                    }
                });

                // Make sure user has enough space remaining
                if (_owner != null)
                {
                    var lockEntry = ServerContext.ServiceTable[_owner].UserLock;
                    await lockEntry.ObtainExclusiveWriteAsync();

                    var userManager = new WebUserManager(ServerContext);
                    var ownerData   = await userManager.FindUserByUsernameAsync(_owner);

                    var afterUploadSpace = ownerData.StorageUsage + uploadStreamFileSize;
                    if (afterUploadSpace > ownerData.StorageQuota)
                    {
                        lockEntry.ReleaseExclusiveWrite();
                        // Throw exception, catch block will remove file and rethrow
                        throw new QuotaExceededException();
                    }
                    // Increase user storage usage
                    ownerData.StorageUsage += uploadStreamFileSize;
                    await userManager.UpdateUserInDatabaseAsync(ownerData);

                    lockEntry.ReleaseExclusiveWrite();
                }
            }
            catch (QuotaExceededException)
            {
                // Roll back write
                await Task.Run(() => File.Delete(targetFile));

                throw;
            }

            return(new FileUploadResult
            {
                FileId = fileId,
                Size = uploadStreamFileSize
            });
        }
Exemplo n.º 3
0
        public ApiAccessModule() : base("/api")
        {
            this.RequiresAuthentication();
            this.RequiresClaims(x => x.Value == ApiClientAuthenticationService.StatelessAuthClaim.Value);

            Get("/userinfo", async _ =>
            {
                var user = await WebUserManager.FindUserByUsernameAsync(Context.CurrentUser.Identity.Name);
                return(Response.AsJsonNet(user));
            });
        }
Exemplo n.º 4
0
        public ApiAccessModule(IPenguinUploadContext serverContext) : base("/api")
        {
            ServerContext = serverContext;
            this.RequiresAuthentication();
            // Requires API key access
            this.RequiresClaims(x => x.Value == ApiClientAuthenticationService.StatelessAuthClaim.Value);

            var userManager = new WebUserManager(ServerContext);

            // Get user metadata
            Get("/userinfo", async _ =>
            {
                var idUsername = Context.CurrentUser.Identity.Name;
                var user       = await userManager.FindUserByUsernameAsync(idUsername);
                return(Response.AsJsonNet(user));
            });

            // Generate new API key
            Patch("/newkey", async _ =>
            {
                var idUsername = Context.CurrentUser.Identity.Name;
                var user       = await userManager.FindUserByUsernameAsync(idUsername);
                // Update key
                await userManager.GenerateNewApiKeyAsync(user);
                return(Response.AsJsonNet(user));
            });

            // Get list of files
            Get("/files", async _ =>
            {
                var idUsername         = Context.CurrentUser.Identity.Name;
                var user               = await userManager.FindUserByUsernameAsync(idUsername);
                var storedFilesManager = new StoredFilesManager(ServerContext);
                var userFiles          = await storedFilesManager.GetStoredFilesByUserAsync(user);
                var directoryStructure = FileOrganization.BuildStructure(userFiles);
                return(Response.AsJsonNet(directoryStructure));
            });

            // Upload a file
            Post("/upload", async _ =>
            {
                var idUsername        = Context.CurrentUser.Identity.Name;
                var request           = this.Bind <FileUploadRequest>();
                var fileUploadHandler = new LocalStorageHandler(ServerContext, idUsername);
                FileUploadResult uploadResult;
                try
                {
                    uploadResult =
                        await fileUploadHandler.HandleUploadAsync(request.File.Name, request.File.Value);
                }
                catch (QuotaExceededException qEx)
                {
                    return(Response.AsText(qEx.Message).WithStatusCode(HttpStatusCode.Forbidden));
                }

                // Register uploaded file
                var storedFilesManager = new StoredFilesManager(ServerContext);
                var storedFile         =
                    await storedFilesManager.RegisterStoredFileAsync(idUsername,
                                                                     request.File.Name, request.TargetDirectory, uploadResult.FileId,
                                                                     uploadResult.Size);

                return(Response.AsJsonNet(storedFile));
            });

            // Force download, bypass password
            Get("/fdownload/{id}", async args =>
            {
                var idUsername         = Context.CurrentUser.Identity.Name;
                var storedFilesManager = new StoredFilesManager(ServerContext);
                var storedFile         = await storedFilesManager.GetStoredFileByIdentifierAsync((string)args.id);
                if (storedFile == null)
                {
                    return(HttpStatusCode.NotFound);
                }

                var fileUploadHandler = new LocalStorageHandler(ServerContext, idUsername);
                var fileStream        = fileUploadHandler.RetrieveFileStream(storedFile.Identifier);
                var response          = new StreamResponse(() => fileStream, MimeTypes.GetMimeType(storedFile.Name));
                return(response.AsAttachment(storedFile.Name));
            });

            // Set a password on a file
            Patch("/lock/{idPass}", async args =>
            {
                var idParts = ((string)args.idPass).Split('!');
                if (idParts.Length < 2)
                {
                    return(HttpStatusCode.BadRequest);
                }
                var id   = idParts[0];
                var pass = idParts[1];
                if (pass.Length > 128)
                {
                    return(Response.AsText("Password cannot exceed 128 characters.")
                           .WithStatusCode(HttpStatusCode.BadRequest));
                }
                // Update file metadata
                var storedFilesManager = new StoredFilesManager(ServerContext);
                var storedFile         = await storedFilesManager.GetStoredFileByIdentifierAsync(id);
                if (storedFile == null)
                {
                    return(HttpStatusCode.BadRequest);
                }
                await storedFilesManager.SetFilePasswordAsync(storedFile, pass);
                return(HttpStatusCode.OK);
            });

            // Unset a password on a file
            Patch("/unlock/{id}", async args =>
            {
                var id = (string)args.id;
                // Update file metadata
                var storedFilesManager = new StoredFilesManager(ServerContext);
                var storedFile         = await storedFilesManager.GetStoredFileByIdentifierAsync(id);
                if (storedFile == null)
                {
                    return(HttpStatusCode.BadRequest);
                }
                await storedFilesManager.SetFilePasswordAsync(storedFile, null);
                return(HttpStatusCode.OK);
            });

            Patch("/rename/{id}/{name}", async args =>
            {
                var id      = (string)args.id;
                var newname = (string)args.name;
                // Update file metadata
                var storedFilesManager = new StoredFilesManager(ServerContext);
                var storedFile         = await storedFilesManager.GetStoredFileByIdentifierAsync(id);
                if (storedFile == null)
                {
                    return(HttpStatusCode.BadRequest);
                }
                storedFile.Name = newname;
                await storedFilesManager.UpdateStoredFileInDatabaseAsync(storedFile);
                return(HttpStatusCode.OK);
            });

            // Delete a file
            Delete("/delete/{id}", async args =>
            {
                var idUsername = Context.CurrentUser.Identity.Name;
                var fileId     = (string)args.id;
                // Remove physical file
                var fileUploadHandler = new LocalStorageHandler(ServerContext, idUsername);
                await fileUploadHandler.DeleteFileAsync(fileId);
                // Unregister file
                var storedFilesManager = new StoredFilesManager(ServerContext);
                await storedFilesManager.UnregisterStoredFileAsync(fileId);
                return(HttpStatusCode.OK);
            });

            // Nuke (batch destroy)

            // Delete all a user's files
            Delete("/nuke/files", async _ =>
            {
                var idUsername         = Context.CurrentUser.Identity.Name;
                var user               = await userManager.FindUserByUsernameAsync(idUsername);
                var storedFilesManager = new StoredFilesManager(ServerContext);
                var fileUploadHandler  = new LocalStorageHandler(ServerContext, idUsername);
                // Start tasks to nuke user's files
                var userFiles             = await storedFilesManager.GetStoredFilesByUserAsync(user);
                var nukePhysicalFilesTask = fileUploadHandler.NukeAllFilesAsync(userFiles.Select(x => x.Identifier));
                var nukeFilesTask         = storedFilesManager.NukeAllFilesAsync(user);
                return(HttpStatusCode.OK);
            });

            // Delete a user and all content
            Delete("/nuke/user", async _ =>
            {
                var idUsername = Context.CurrentUser.Identity.Name;
                var user       = await userManager.FindUserByUsernameAsync(idUsername);
                // Disable user
                await userManager.SetEnabledAsync(user, false);
                var storedFilesManager = new StoredFilesManager(ServerContext);
                var fileUploadHandler  = new LocalStorageHandler(ServerContext, idUsername);
                // Start tasks to nuke user's files
                var userFiles             = await storedFilesManager.GetStoredFilesByUserAsync(user);
                var nukePhysicalFilesTask = fileUploadHandler.NukeAllFilesAsync(userFiles.Select(x => x.Identifier));
                var nukeFilesTask         = storedFilesManager.NukeAllFilesAsync(user);
                await nukeFilesTask;
                await nukePhysicalFilesTask;
                // Now nuke the user
                await userManager.RemoveUserAsync(user.Username);
                return(HttpStatusCode.OK);
            });
        }
Exemplo n.º 5
0
        public AdminAccessModule(IPenguinUploadContext serverContext) : base("/api/admin")
        {
            ServerContext = serverContext;

            this.RequiresAuthentication();
            // Requires API key access
            this.RequiresClaims(x => x.Value == ApiClientAuthenticationService.StatelessAuthClaim.Value);

            Before += (ctx) =>
            {
                // Make sure user is an admin
                if (!ServerContext.IsAdministrator(Context.CurrentUser.Identity.Name))
                {
                    return(HttpStatusCode.Unauthorized);
                }
                return(null);
            };

            // List all users
            Get("/enumerateusers", async _ =>
            {
                var webUserManager = new WebUserManager(ServerContext);
                var allUsers       = await webUserManager.GetAllUsersAsync();
                return(Response.AsJsonNet(allUsers));
            });

            // Get user account info
            Get("/accountinfo/{name}", async args =>
            {
                var userManager = new WebUserManager(ServerContext);
                var user        = await userManager.FindUserByUsernameAsync((string)args.name);
                return(user == null ? HttpStatusCode.NotFound : Response.AsJsonNet(user));
            });

            // Disable a user's account
            Patch("/disableuser/{name}", async args =>
            {
                var userManager = new WebUserManager(ServerContext);
                var user        = await userManager.FindUserByUsernameAsync((string)args.name);
                if (user == null)
                {
                    return(HttpStatusCode.BadRequest);
                }
                // Disable user
                await userManager.SetEnabledAsync(user, false);
                return(HttpStatusCode.OK);
            });

            // Enable a user's account
            Patch("/enableuser/{name}", async args =>
            {
                var userManager = new WebUserManager(ServerContext);
                var user        = await userManager.FindUserByUsernameAsync((string)args.name);
                if (user == null)
                {
                    return(HttpStatusCode.BadRequest);
                }
                // Disable user
                await userManager.SetEnabledAsync(user, true);
                return(HttpStatusCode.OK);
            });

            // Get file info (admin override)
            Get("/fileinfo/{id}", async args =>
            {
                var fileId = (string)args.id;
                // Get metadata
                var storedFilesManager = new StoredFilesManager(ServerContext);
                var storedFile         = await storedFilesManager.GetStoredFileByIdentifierAsync(fileId);
                return(Response.AsJsonNet(storedFile));
            });

            // Download a file (admin override)
            Get("/downloadfile/{id}", async args =>
            {
                var fileId = (string)args.id;
                // Get metadata
                var storedFilesManager = new StoredFilesManager(ServerContext);
                var storedFile         = await storedFilesManager.GetStoredFileByIdentifierAsync(fileId);
                if (storedFile == null)
                {
                    return(HttpStatusCode.NotFound);
                }
                var fileUploadHandler = new LocalStorageHandler(ServerContext, null, true);
                var fileStream        = fileUploadHandler.RetrieveFileStream(storedFile.Identifier);
                var response          = new StreamResponse(() => fileStream, MimeTypes.GetMimeType(storedFile.Name));
                return(response.AsAttachment(storedFile.Name));
            });

            // Delete a file (admin override)
            Delete("/deletefile/{id}", async args =>
            {
                var fileId = (string)args.id;
                // Remove physical file
                var fileUploadHandler = new LocalStorageHandler(ServerContext, null, true);
                await fileUploadHandler.DeleteFileAsync(fileId);
                // Unregister file
                var storedFilesManager = new StoredFilesManager(ServerContext);
                await storedFilesManager.UnregisterStoredFileAsync(fileId);
                return(HttpStatusCode.OK);
            });

            // Quota management
            Patch("/updatequota/{name}/{quota}", async args =>
            {
                var userManager = new WebUserManager(ServerContext);
                var user        = await userManager.FindUserByUsernameAsync((string)args.name);
                if (user == null)
                {
                    return(HttpStatusCode.BadRequest);
                }
                // Disable user
                await userManager.SetQuotaAsync(user, (int)args.quota);
                return(HttpStatusCode.OK);
            });
        }
Exemplo n.º 6
0
        public RemoteAuthModule(IPenguinUploadContext serverContext)
        {
            ServerContext = serverContext;
            Post("/register", async args =>
            {
                var req = this.Bind <RegistrationRequest>();

                try
                {
                    if (!ServerContext.Configuration.RegisterEnabled)
                    {
                        return(Response.AsText("Account registration has been disabled by the administrator.")
                               .WithStatusCode(HttpStatusCode.Unauthorized));
                    }

                    // Validate parameters!

                    // Valdiate username length, charset
                    if (req.Username.Length < 4)
                    {
                        throw new SecurityException("Username must be at least 4 characters.");
                    }
                    // Validate phone number

                    // Validate password
                    if (req.Password.Length < 8)
                    {
                        throw new SecurityException("Password must be at least 8 characters.");
                    }

                    if (req.Username.Length > 24)
                    {
                        throw new SecurityException("Username may not exceed 24 characters.");
                    }

                    if (req.Password.Length > 128)
                    {
                        throw new SecurityException("Password may not exceed 128 characters.");
                    }

                    // Check invite key if enabled
                    if (!string.IsNullOrWhiteSpace(ServerContext.Configuration.InviteKey))
                    {
                        if (req.InviteKey != ServerContext.Configuration.InviteKey)
                        {
                            throw new SecurityException("The invite key is not recognized.");
                        }
                    }

                    // Validate registration
                    var webUserManager = new WebUserManager(ServerContext);
                    var newUser        = await webUserManager.RegisterUserAsync(req);

                    // Return user details
                    return(Response.AsJsonNet(new RemoteAuthResponse
                    {
                        User = newUser,
                        ApiKey = newUser.ApiKey
                    }));
                }
                catch (NullReferenceException)
                {
                    // A parameter was not provided
                    return(HttpStatusCode.BadRequest);
                }
                catch (SecurityException secEx)
                {
                    // Registration blocked for security reasons
                    return(Response.AsText(secEx.Message)
                           .WithStatusCode(HttpStatusCode.Unauthorized));
                }
            });

            Post("/login", async args =>
            {
                var req            = this.Bind <LoginRequest>();
                var webUserManager = new WebUserManager(ServerContext);
                var selectedUser   = await webUserManager.FindUserByUsernameAsync(req.Username);

                if (selectedUser == null)
                {
                    return(HttpStatusCode.Unauthorized);
                }

                try
                {
                    // Validate password
                    if (selectedUser.Enabled && await webUserManager.CheckPasswordAsync(req.Password, selectedUser))
                    {
                        // Return user details
                        return(Response.AsJsonNet(new RemoteAuthResponse
                        {
                            User = selectedUser,
                            ApiKey = selectedUser.ApiKey
                        }));
                    }
                    return(HttpStatusCode.Unauthorized);
                }
                catch (NullReferenceException)
                {
                    // A parameter was not provided
                    return(HttpStatusCode.BadRequest);
                }
                catch (SecurityException secEx)
                {
                    // Blocked for security reasons
                    return(Response.AsText(secEx.Message)
                           .WithStatusCode(HttpStatusCode.Unauthorized));
                }
            });

            Post("/reauth", async args =>
            {
                var req            = this.Bind <ReauthRequest>();
                var webUserManager = new WebUserManager(ServerContext);
                var selectedUser   = await webUserManager.FindUserByUsernameAsync(req.Username);

                if (selectedUser == null)
                {
                    return(HttpStatusCode.Unauthorized);
                }

                try
                {
                    // Validate key
                    if (selectedUser.Enabled && selectedUser.ApiKey == req.ApiKey)
                    {
                        // Return user details
                        return(Response.AsJsonNet(new RemoteAuthResponse
                        {
                            User = selectedUser,
                            ApiKey = selectedUser.ApiKey
                        }));
                    }
                    return(HttpStatusCode.Unauthorized);
                }
                catch (NullReferenceException)
                {
                    // A parameter was not provided
                    return(HttpStatusCode.BadRequest);
                }
                catch (SecurityException secEx)
                {
                    // Blocked for security reasons
                    return(Response.AsText(secEx.Message)
                           .WithStatusCode(HttpStatusCode.Unauthorized));
                }
            });

            Patch("/changepassword", async args =>
            {
                var req            = this.Bind <ChangePasswordRequest>();
                var webUserManager = new WebUserManager(ServerContext);
                var selectedUser   = await webUserManager.FindUserByUsernameAsync(req.Username);

                try
                {
                    // Validate password
                    if (req.NewPassword.Length < 8)
                    {
                        throw new SecurityException("Password must be at least 8 characters.");
                    }

                    if (req.NewPassword.Length > 128)
                    {
                        throw new SecurityException("Password may not exceed 128 characters.");
                    }

                    if (selectedUser.Enabled && await webUserManager.CheckPasswordAsync(req.OldPassword, selectedUser))
                    {
                        // Update password
                        await webUserManager.ChangeUserPasswordAsync(selectedUser, req.NewPassword);
                        return(HttpStatusCode.OK);
                    }
                    return(HttpStatusCode.Unauthorized);
                }
                catch (NullReferenceException)
                {
                    // A parameter was not provided
                    return(new Response().WithStatusCode(HttpStatusCode.BadRequest));
                }
                catch (SecurityException secEx)
                {
                    // Registration blocked for security reasons
                    return(Response.AsText(secEx.Message)
                           .WithStatusCode(HttpStatusCode.Unauthorized));
                }
            });
        }
Exemplo n.º 7
0
 public AccountController(SignInManager <ApplicationUser> signInManager, WebUserManager webUserManager)
 {
     _signInManager  = signInManager;
     _webUserManager = webUserManager;
 }
Exemplo n.º 8
0
 //User Manager
 public static ChangePassViewModel ToModel(this WebUserManager entity)
 {
     return(Mapper.Map <WebUserManager, ChangePassViewModel>(entity));
 }
Exemplo n.º 9
0
        public RemoteAuthModule()
        {
            Post("/register", async args =>
            {
                var req = this.Bind <RegistrationRequest>();

                try
                {
                    // Validate parameters!

                    // Valdiate username length, charset
                    if (req.Username.Length < 4)
                    {
                        throw new SecurityException("Username must be at least 4 characters.");
                    }
                    // Validate phone number

                    // Validate password
                    if (req.Password.Length < 8)
                    {
                        throw new SecurityException("Password must be at least 8 characters.");
                    }

                    if (req.PhoneNumber != null && !StringUtils.IsPhoneNumber(req.PhoneNumber))
                    {
                        throw new SecurityException("Phone number was of invalid format.");
                    }

                    // Validate registration
                    var newUser = await WebUserManager.RegisterUserAsync(req);

                    // Return user details
                    return(Response.AsJsonNet(new RemoteAuthResponse
                    {
                        User = newUser,
                        ApiKey = newUser.ApiKey,
                    }));
                }
                catch (ArgumentNullException)
                {
                    // A parameter was not provided
                    return(new Response().WithStatusCode(HttpStatusCode.BadRequest));
                }
                catch (NullReferenceException)
                {
                    // A parameter was not provided
                    return(new Response().WithStatusCode(HttpStatusCode.BadRequest));
                }
                catch (SecurityException secEx)
                {
                    // Registration blocked for security reasons
                    return(Response.AsText(secEx.Message)
                           .WithStatusCode(HttpStatusCode.Unauthorized));
                }
            });

            Post("/login", async args =>
            {
                var req = this.Bind <LoginRequest>();

                var selectedUser = await WebUserManager.FindUserByUsernameAsync(req.Username);

                try
                {
                    // Validate password
                    if (await WebUserManager.CheckPasswordAsync(req.Password, selectedUser))
                    {
                        // Return user details
                        return(Response.AsJsonNet(new RemoteAuthResponse
                        {
                            User = selectedUser,
                            ApiKey = selectedUser.ApiKey,
                        }));
                    }
                    else
                    {
                        return(new Response().WithStatusCode(HttpStatusCode.Unauthorized));
                    }
                }
                catch (ArgumentNullException)
                {
                    // A parameter was not provided
                    return(new Response().WithStatusCode(HttpStatusCode.BadRequest));
                }
                catch (NullReferenceException)
                {
                    // A parameter was not provided
                    return(new Response().WithStatusCode(HttpStatusCode.BadRequest));
                }
                catch (SecurityException secEx)
                {
                    // Registration blocked for security reasons
                    return(Response.AsText(secEx.Message)
                           .WithStatusCode(HttpStatusCode.Unauthorized));
                }
            });
        }