Sharing a file in OneDrive between different users of the same app - c#

My UWP app needs to share some xml files between different users.
Let's say user A creates the files, and user B needs to access them (read and write).
The files are saved by user A to the App folder on her OneDrive (OneDrive > Apps > MyApp > file.xml).
Now when user B is using the app, he needs to access the files on A's OneDrive.
As far as I can tell, using the C# OneDrive SDK I have two ways to have B access the files:
1) User A shares the MyApp folder with user B, and sends him the folder id. User B enters the folder id in the app and the app can get to the files using the folder id.
2) User A shared the MyApp folder with user B; user B adds the shared folder to his OneDrive; now the app can search for the folder by looking through the children of Drive/Root and finding a folder that has the right name and has a remote item. The app can get to the files using the remote item id.
I don't really like either solution because both of them rely on work by the user that is error prone and likely not something that they have had to do before (sending a weird id in an email, entering it in the app, or adding the shared folder to one's OneDrive).
Ideally I would have user A share the folder with B and then the app would somehow find it through B's OneDrive (without B explicitly adding it) but I haven't found a way to do that with the C# SDK.

For whoever has the same problem:
As it turns out, it should be possible to find folders shared with the user through the API, but it doesn't work because of this bug: https://github.com/OneDrive/onedrive-sdk-csharp/issues/133
There is a fix for the bug that applies only to version 1.2 of the API amd it can be found in this branch: https://github.com/OneDrive/onedrive-sdk-csharp/tree/v1-maintenance

Related

How to restrict a website to get access to a specific path through IIS?

I'm looking for a way to restrict a website served by IIS so that the website can get access to the specific folder or drive not more, let me illustrate it.
Imagine I have two websites A and B served by IIS, you can put following code in code-behind of both websites:
string windowsPath = Environment.GetFolderPath(Environment.SpecialFolder.Windows)
string path = windowsPath + #"\Microsoft.NET\Framework";
var directories = Directory.GetDirectories(path);
I need a way through IIS to restrict website A not be able to get access to the mentioned directories and only website B be able to do that. In other words I want to restrict read access.
I suppose it should have a simple solution because it's what hosting servers deal with. It's obvious that you can't put a piece of code in your website in a web hosting server and simply get access to list files name located in drive C of the hosting server.
How can I achieve that?
After researching a lot I found the solution, I thought it might be useful for ones who will stumble upon this matter later, so I documented the solution.
Note:
From IIS 7.5 on, you have more access on user who is running a website.
Every application pool you make, creates an internal user which is hidden and is known as AppPoolIdentity.
The goal:
Imagine We have two websites A and B, we also have a folder named SecurityTest located in D:\Temp, there are 6 folders inside it under the names 1 to 6, we consider to allow website A get the name of the folders inside SecurityTest while we tend to prevent website B to do that.
Step 1:
Firstly, create a website through VisualStudio, I put a server side button in the form, I consider to get name of folders in the specified path (say D:\Temp\SecurityTest), So here's the code I place in code behind to be triggered when the button is clicked:
protected void Button1_Click(object sender, EventArgs e)
{
Label1.Text = string.Empty;
string path = #"D:\Temp\SecurityTest";
var directories = Directory.GetDirectories(path);
for (int i = 0; i < directories.Length; i++)
{
string fileName = Path.GetFileName(directories[i]);
Label1.Text += fileName + "<br />";
}
}
Step 2: Now let's deal with IIS. Add two websites (or applications) to the IIS, name them A and B, the physical path for both are the same, only change port number, for instance set 81 as port number for website A and 82 for website B. Note that new application pool is created by default with the same name of your website (if you create a new application instead of new website, you should create a new application pool by yourself).
Step 3: Now in the Connections pane, click on website A, from middle pane, double click on Authentication located in the IIS category. Then click on Anonymous Authentication, after that from 'Actions' pane at the right side, click on Edit.
Now select Application pool identity and click on OK. By following these steps you chose AplicationPoolIdentity user as the user who handles website A. Follow these steps for website B.
Step 4: Go to the pathD:\Temp, right click on the folder named SecurityTest, on the Security tab, on the Group or user names category, you can see users listed who have access to the folder, these users are granted permission at the creation time by default. You might see more or less though but the point is that you should add website A ApplicationPoolIdentity user and remove all other users, so remove Users which gives access to all users, after that remove Authenticated users from the list too.
Keep in mind that you can't simply remove these users, you should Disable Inheritance first. here's the steps to achieve that:
Since you tend to allow website A to get directories, you need to add the user corresponding to the website A, now you need to follow the next step.
Step 4-1: On the same dialogue, click on Add to add new user, from here you can't find the user related to the website A since it's a hidden and internal (and virtual) user, I mean the AppPoolIdentity user for website A. You should type the name on the following pattern:
IIS APPPOOL\<app_pool_name>
So for website A I should type IIS APPPOOL\A, click on Check Names to make sure whether the user exists or not, finally press OK button.
Step 4-2: To prevent other users to get access to the webite A, click on Advanced button, click on Disable inheritance, when you encounter the warning message, select the first option (Convert) preferably, then press OK to close the dialogue.
Now in Security tab, click on Edit button to change permissions. Here you can remove users you don't need, like Authenticated Users and Users. From now on both websites A and B won't be able to get folders name.
Now get back to IIS panel and click on website A in the left Pane, then click on Browse *:81 (http) link, you can see the website A on your browser, do the same for website B to open it in the browser. When you click on button in website A you can observe a list of folders from 1 t 6 while you get following error when you click on the button to get directories on the website B.
Access to the path 'D:\Temp\SecurityTest' is denied.
That's all you need to do.
If you understand how pipeline work, you would know that we can only filter permission based by injecting module. So there are few things we can do with IIS configuration.
Asp.net application activated under IIS worker process with Application pool identity. Since Site A and Site B used different managed service account. You could remove IIS apppool\A's permission to prevent site A from reading folder.
Since read permission for application pool identity to access windows\microsoft.net is necessary when activating worker process. It is not recommended to restrict the permission

How to direct shared path to Microsoft.Data.SQLite Connection String? (UWP)

i'm making 2 UWP apps, and i want to make them share 1 DB.
i'm using Microsoft.Data.SQLite
however, is there any way to share the same DB??
SqliteConnection db = new SqliteConnection("Filename=data.db"));
"Filename=data.db" path was c:\Users(user
name)\AppData\Local\Packages(App ID)\LocalState\data.db
However, I know UWP app can only access that c:\Users\ (username)\AppData\Local\Packages(App ID)\LocalState\ folder except shared app data folders.
So, can you tell me how to direct the shared app data folder to Connection String?
Are two ways to that:
1) Creates a button to call user action to select the common folder using a Picker to file or folder. Your application stores the access token returned by this explicit authorization and use that in future with no new user interaction.
2) Have a few ways to app get store authorization, but some that needs an enterprise Windows Store association (like Documents Library). I not sure, but for some locations, in the app validation you will be required to justify the needs before to publish your app.
More details in here: https://learn.microsoft.com/en-us/windows/uwp/files/file-access-permissions. See the title "Accessing additional locations".

What is the best Environment.SpecialFolder for store application data in Xamarin.Forms?

I'm new in Xamarin.Forms and mobile development. I want to store user and encrypted password of my application user in file on mobile device. I'm using xamarin forms technology. I kwnow that there are many differenet folders. In example:
System.Environment.SpecialFolder.Personal
System.Environment.SpecialFolder.LocalApplicationData
System.Environment.SpecialFolder.MyDocuments
Full list you can find here: https://msdn.microsoft.com/en-gb/en-enl/library/system.environment.specialfolder(v=vs.110).aspx
What is the best folder / catalog for store:
user and password data
other application specyfic data
??
Edit: I have found that "Personal" is good for me, but if you have other answers post it as well. SpecialFolder.Personal location
Storing small Key-Value Pairs:
Xamarin.Forms implements Application.Current.Properties which stores the key value data in the local storage of the app and access to these key-value pairs are secure to that app only who stored them.
Storing Documents/Database (Sqlite):
Each platform has it's own folder structure to store app specific data/files underneath.
Android:
Environment.SpecialFolder.Personal & MyDocuments both maps to: /data/data/#PACKAGE_NAME#/files
Environment.SpecialFolder.LocalApplicationData maps to: /data/data/#PACKAGE_NAME#/files/.local/share
We can store files in any of the above directories based on how they are mapped in the file system.
None of the above directories can be accessed by other app, nor user can access them outside the world unless the phone is rooted.
iOS:
Environment.SpecialFolder.Personal, LocalApplicationData & MyDocuments all map to: /Documents
iOS has following directory structure:
/Documents
/Library
/Library/Application Support
/Library/Caches
/tmp
/Documents: Gets visible in iTunes If iTunes sharing is turned on in info.plist in the app. Content can be backed up by iTunes/iCloud.
/Library: Not visible in iTunes. Can be backed up by iTunes/iCloud except Caches directory.
Files/Data which doesn't need to expose to user should be stored in Library directory. Ex. database files. I would go for Library directory for add on security along with encryption (if required).
To get to the Library Path:
Path.Combine(Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments), "..", "Library");
To know more on each Enumeration's mapping with directory Go Here.
Find basics about iOS File System Basics.

ASP.Net "Access to the path '' is denied."File Upload Control not Working in Web Server (IIS7)

I'm currently developing a website application and one of its features is to be able to upload and download the files. All the uploaded files will be stored in the external network location. First is on page load, it will create a temporary folder and all of the uploaded files will be stored there. Then when they click the save button, it will create a folder where it will be permanently stored and put all the files in the folder and remove automatically remove the temporary folder. It is working fine in my local host server, but when I upload it and put to web server, it throws an error, Access to the path '(network path)' is denied.
ASP.NET is not authorized to access the requested resource. Consider granting access rights to the resource to the ASP.NET request identity. ASP.NET has a base process identity (typically {MACHINE}\ASPNET on IIS 5 or Network Service on IIS 6 and IIS 7, and the configured application pool identity on IIS 7.5) that is used if the application is not impersonating. If the application is impersonating via , the identity will be the anonymous user (typically IUSR_MACHINENAME) or the authenticated request user.
To grant ASP.NET access to a file, right-click the file in File Explorer, choose "Properties" and select the Security tab. Click "Add" to add the appropriate user or group. Highlight the ASP.NET account, and check the boxes for the desired access.
I've researched for a solution for almost a week now and it says it's something about permission, but all of the solutions on the net are not clear and doesn't work for me. I hope someone could help me with the step by step instruction on how to configure permissions to be able to allow network access o any possible working solutions.
UPDATE:
Here is the current screenshot:
Permission for the web site in IIS7
I hae downloaded the ASP.NET components but I can't find the ASP.NET account. I have .net 4.0 application pool. Should I give permission on my uploading folder? Please help me.
Thank you everyone.
This is a permission issue and you already have a hint :
To grant ASP.NET access to a file, right-click the file in File Explorer, choose "Properties" and select the Security tab. Click "Add" to add the appropriate user or group. Highlight the ASP.NET account, and check the boxes for the desired access.
Explore to IIS manager.
Expand Sites node and find your site then right click.
Click Explore and you will be redirected to the physical file path.
Right click the folder and go to security tab
Click Edit button (another window will pop up)
In this window add the iis user normally it is prefix with IIS_MACHINENAME
Set full permission to this user and you are good to go.
I struggled with this same issue and while we did all the permission changes shown I was still getting the error. In the end I wrote a small test page using the file upload control and when I tried it with various files it worked fine.
What I discovered was that there was a slight difference between these two file names and that was causing the error
this_file1.ppf
thisfile1.pdf
Yes, the underscore was causing the access violation error and for the life of me I do not know why? This also applies to files with a space in the file name. We are running the webserver (IIS7) on a Windows Server 2012 R2 if that makes a difference.
I did not find any reference to this in the control though it will fail on long file names as well.
Fixed mine by:
File properties
Under the security tab click add
Add the iis user which is in my case IIS_IUSRS and then click Check Names
Click OK and grant full-access from the permissions category
If you cant find IIS_IUSRS you can always go to Security > Add > Advanced > Find Now to find the IIS username.
I've also added the current logged in user by typing in the current logged in username and granted full-access
In my case , i just copied required files to wwwroot folder in c Drive, and changed the physical path , it solved my issue.
Just a hint: in my case, the following code doesn't work and emits the message “Access to the path (...) is denied.”
var Request = HttpContext.Current.Request;
foreach (string file in Request.Files)
{
var postedFile = Request.Files[file];
postedFile.SaveAs(pathToSave);
}
This one works fine:
var Request = HttpContext.Current.Request;
foreach (string file in Request.Files)
{
var postedFile = Request.Files[file];
using (var stream = new FileStream(pathToSave, FileMode.Create))
{
await postedFile.InputStream.CopyToAsync(stream);
}
}

how do I access a folder on the shared hosting space?

I am trying to upload image files to the server and it gives me an error
"System.UnauthorizedAccessException: Access to the path 'D:\Hosting\234344\html\Testingfiles\upload\813.jpg' is denied.at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)"
in the HttpHandler I have :
HttpPostedFile file = context.Request.Files["Filedata"];
string usr_id = context.Request.Form["usr_id"];// gets the JSON data from the request
string strPath = context.Server.MapPath(("/Testingfiles/upload/") + file.FileName);
string ext = Path.GetExtension(strPath);
if (ext.Equals(".jpg") || ext.Equals(".jpeg") || ext.Equals(".png"))
{
file.SaveAs(strPath);
context.Response.Write("Image uploaded successfully");
}
what am i doing wrong here?
The error message says it all. You don't have write access to that folder.
You will need to ask your hosting provider to assign write rights to that folder for the ASP .NET identity.
Also, consider if you can use a folder below ~/App_Data. This is by convention the place to store files that needs write access in ASP .NET, so many hosting providers will allow writes to this folder by default (but you would need to check yourself for your specific host to be sure).
You should try writing to ~/App_Data/ to see if that works. If it does then its just because you haven't given asp.net write permission to the /TestingFiles/Uploads/ folder.
If your control panel has Plesk on it then you can sort this out yourself by going to the FileManager and clicking the permissions button. If you look at your App_Data file permissions for reference, the actual username that you need to add will vary depending on your domain name with plesk.
Other hosting control panels may allow you to do it in different ways.
If you can't find it then you should ask your host how you set up file permissions or look in their knowledge base.
If your control panel has Plesk on it then you can sort this out yourself by going to the FileManager and clicking the permissions button.
I fixed this error by allowing IIS users full access to upload folder. No need to use App_Data folder
For Plesk 12.0 only:
No need to use App Data folder. You just have to give full control to your Application pool group IWPG(username). It will surely work. I searched for many hours and this solution worked for me .
Hope It works for others too.

Categories

Resources