Hi!
I would like to propose adding a feature for participant-specific file access control
A while ago I had a call with @lostintangent and @fubaduba about my educational use case for Live Share. I'm the guy behind code-workshop-kit which is a tool built on top of Live Share for facilitating remote code workshops.
For context, I use Live Share for my training sessions and I usually have a folder participants in my workspace, in which I automatically scaffold a folder for each of my Live Share participants, which they do the training inside of, with regards to exercises etc.
I remember that I was asked in the call about whether I need to change file access based on specific participants, for example if I don't want students to cheat on exercises by peeking into the code of their peers. I answered that for me it is not important because I mostly teach (young) professionals, who are responsible enough to "peek responsibly" π.
However, this changed, as there is now a lot more interest for code-workshop-kit and using Live Share for online education in universities and high schools, and by far the most common question I get from them is: How can I ensure my students don't see each others code and cheat on exercises?
Therefore, I think it would be really cool to add this feature. I would summarize the requirement as:
Live Share should support an option where participants see all files except those inside folders that belong to peers.
Or to make it more generic
Hosts should be able to restrict access to files based on which participant is looking.
I want to do more than just "request a feature", I'm very happy to collaborate and think about some solutions, perhaps even implement them with some help.
I think it makes sense to explore whether .vsls.json can be used to accomplish the use case; it seems like the right place in terms of "purpose", since it handles file access and visibility.
The basic assumptions for my suggestions are that, under the hood where the config is parsed and applied, we:
Examples with requirement "participants should see all files except those inside folders of their peers", assuming current user jorenbroekema:
/participants/jorenbroekema/index.html βοΈ/participants/lostintangent/index.html β (not inside participants/${currentUser})/participants/jorenbroekema/secret.p12 β(excluded by excludeFiles, even though it is accessible from a participants-access perspective)/index.html βοΈ (not inside peer participants folders so we don't want to restrict)So let's explore a hypothetical .js config file (.vsls.js or .vsls.config.js or something), where you can get a bit more fine-grained control. This is probably how I would prefer the API to be if I'm only looking at myself.
export default {
$schema: "http://json.schemastore.org/vsls",
gitignore: "none",
fileIsExcluded: (participantName, filePath) => {
// If the file is outside of the participants folder, show it.
// If it's inside, only show it if the file is in the folder of the current participant
// No peeking files from other students! >:)
if (!filePath.startsWith(`/participants/`) || filePath.startsWith(`/participants/${participantName}`)) {
return true;
}
return false;
},
// These rules apply on top and will override the above
excludeFiles: [
"*.p12",
"*.cer",
"token",
".gitignore"
],
}
This default export would be loaded by the config loader and it parses fileIsExcluded as a function and calls it with the participant name and the filepath of the file that it needs to consider to be shown or not shown.
I suppose VS Live Share would search for either .vsls.js or .vsls.json and prioritise the former if both are found.
This pattern is inspired by other tools inside the JavaScript ecosystem such as ESLint, standard-version, Prettier, lint-staged, husky and more. E.g. for ESLint you can pass .eslintrc.js or .eslintrc.json and even some others. It uses a priority ordering system in terms of which config it uses when presented with multiple.
In my opinion this is a very nice pattern in terms of dev experience because I can choose the level of control that I need.
So let's go back to JSON again, let's see if we can accomplish the same requirement.
Mostly we need to pass to Live Share where the folder is in which the participant-specific folders live, so for example participants, meaning that inside, we have folders named the same as the participants.
{
"$schema": "http://json.schemastore.org/vsls",
"folderWithRestrictedAccessToPeerFolders": "participants",
"excludeFiles": [
"*.p12",
],
}
Kinda verbose name.. which makes sense because the option is quite use-case specific π.
This restricts access to folders inside participants folder. For example, access to participants/jorenbroekema is restricted to user jorenbroekema.
It meets the first requirement but not the second, since it has the specific logic of the JS config suggestion example hard-coded under the hood. However, that's still good enough for my use case I believe π.
I think the JS config way is better to give people flexibility and allow them to specify their own participant-specific file access logic. Perhaps there's other use cases where a host may want to build in some custom file access control in their Live Share sessions π.
I'm sure there's more ideas, and perhaps you may feel like .vsls.json is not the right place to configure participant-specific file access. So of course, feel free to take a completely different approach or throw some other suggestions here :)! In the end, it doesn't matter much to me how it is implemented, as long as I can somehow handle file access on a per participant basis.
Hey! When we last spoke, I was pretty sure you were going to make this request soon π It makes total sense for your use-case, and I'd definitely love to support it. Most of the team is out on holiday right now, so let us give this some thought, and get back to you.
In the meantime, I think your JS-based config proposal seems pretty compelling, and so I'll think through that a bit further. Thanks again for building such an awesome workshop experience around Live Share!
Hehe yeah I guess it was inevitable ;). Thanks for looking into this and happy holidays of course!
This is an awesome proposal!
I wonder if we'd be better off adding something to the extensibility API where extensions can register themselves as "access controllers," and they would provide a fileIsExcluded callback that Live Share would call.
It's very similar to your proposal, but is potentially more flexible and requires less work on Live Share's side π. However, the drawback is that you would have to provide an extension, not just a .vsls.js file, although this doesn't sound like it's an issue for your use-case (and probably most people that need such control need it because of an extension that integrates with Live Share?)
@daytonellwanger Yeah I was thinking the same thing over the weekend π In @jorenbroekema's case, I think an extension will eventually make sense, and since this feature is somewhat domain-specific, I think an extensibility API is a simpler way for us to support this, without adding any complexity for end-users.
So correct me if I'm wrong, the extensibility API, with that you are referring to https://www.npmjs.com/package/vsls where https://github.com/vsls-contrib/whiteboard is an example of a VS Code extension that makes use of this API to hook into Live Share?
And the idea is that you guys would export some kind of callback that I can hook into for deciding whether a file should be accessible at the moment it is requested by a participant? That would definitely be great, and be plenty for me! I fully agree with @lostintangent that it's simpler this way and not adding any complexity for end users.
I also see the extensibility gives you access to a list of the participants and you can listen to events when they join or leave, this is also great!! Just wondering, do you have any starter resources for creating a VS Code extension that hooks into the live share extensibility API? I'll probably figure things out with the example extensions I find from https://github.com/vsls-contrib/awesome-liveshare though any other resource suggestions are very welcome :)!
The Counter is our "hello world" sample, and then the whiteboard is the next simplest. Both of those show how to use the LS API, and in particular, how to expose custom RPC services. If you have any other questions about specific LS APIs, we might be able to point you at other extensions. Otherwise, feel free to ping us with any questions π
As we discussed in our last chat, I'd love to see if we can't drive the participants list from Live Share, and potentially auto-generate new workshop folders when guests join. That way, you wouldn't have to maintain a separate roster file. I also think you could host the "teacher dashboard" as a WebView in VS Code, and potentially streamline the management experience. In general, I'd love to have a "Live Share Workshop" extension, that folks could install and use to run/participant in workspaces π€
Yep that's the idea! I want to get to a point to where the host doesn't have to maintain a list of names because it just uses the list of "peers" I believe it's called in the LS API, this + the file access will be a good start of this plugin and then we can, over time, add more to integrate the workshop experience more with live share itself :)
Most helpful comment
The Counter is our "hello world" sample, and then the whiteboard is the next simplest. Both of those show how to use the LS API, and in particular, how to expose custom RPC services. If you have any other questions about specific LS APIs, we might be able to point you at other extensions. Otherwise, feel free to ping us with any questions π
As we discussed in our last chat, I'd love to see if we can't drive the participants list from Live Share, and potentially auto-generate new workshop folders when guests join. That way, you wouldn't have to maintain a separate roster file. I also think you could host the "teacher dashboard" as a WebView in VS Code, and potentially streamline the management experience. In general, I'd love to have a "Live Share Workshop" extension, that folks could install and use to run/participant in workspaces π€