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(); } }
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 }); }
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)); }); }
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); }); }
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); }); }
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)); } }); }
public AccountController(SignInManager <ApplicationUser> signInManager, WebUserManager webUserManager) { _signInManager = signInManager; _webUserManager = webUserManager; }
//User Manager public static ChangePassViewModel ToModel(this WebUserManager entity) { return(Mapper.Map <WebUserManager, ChangePassViewModel>(entity)); }
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)); } }); }