Spaces:
Runtime error
Runtime error
| class ProjectPermissionManager { | |
| static permissions = { | |
| javascript: true, | |
| camera: true, | |
| allWebsites: true, | |
| cameraPictures: false, | |
| scratchSignIn: true, | |
| limitedWebsites: {} | |
| }; | |
| static permissionMessages = { | |
| javascript: "use custom code in JavaScript", | |
| camera: "turn on your camera", | |
| allWebsites: "display all websites", | |
| cameraPictures: "take screenshots while your camera is on", | |
| scratchSignIn: "sign in with Scratch", | |
| limitedWebsite: "display $0", | |
| }; | |
| static permissionDrawbacks = { | |
| javascript: [], | |
| camera: [], | |
| allWebsites: [], | |
| cameraPictures: ["take a screenshot while your camera is visible"], | |
| scratchSignIn: [], | |
| limitedWebsite: [], | |
| }; | |
| static requiresCode = []; | |
| static disabledPermissions = []; | |
| static get skipPermissionRequest() { | |
| if (!vm) return false; | |
| if (!vm.runtime) return false; | |
| return vm.runtime.isProjectPermissionManagerDisabled === true; | |
| } | |
| static GenerateCode(length) { | |
| return Array.from(new Array(length).keys()).map(() => { return Math.round(Math.random() * 9) }).join(""); // generates something like 281964 | |
| } | |
| static EditPromptForAcceptCheck(string) { | |
| return String(string).replace(/ /gmi, "").toLowerCase(); | |
| } | |
| static RequestPermission(name, ...args) { | |
| // packager | |
| if (ProjectPermissionManager.skipPermissionRequest === true) return true; | |
| if (ProjectPermissionManager.disabledPermissions.includes(name)) return false; | |
| if (name == "limitedWebsite") { | |
| if (args.length < 1) throw new Error("No URL specified what are you trying to get permission for bro"); | |
| if (!ProjectPermissionManager.IsUrlSafe(args[0])) return false; | |
| }; | |
| // check if we already gave permission to do this | |
| if (name == "limitedWebsite") { | |
| if (ProjectPermissionManager.permissions.limitedWebsites[args[0]] == true) return true; | |
| }; | |
| if (ProjectPermissionManager.permissions[name]) return true; | |
| let string = `Allow this project to ${ProjectPermissionManager.permissionMessages[name]}?`; | |
| for (let i = 0; i < args.length; i++) { | |
| const argument = args[i]; | |
| string = string.replace(`$${i}`, (ProjectPermissionManager.IsDataUrl(argument) ? "custom website" : String(argument))); | |
| } | |
| string += `\n\nThis will allow the project to:\n`; | |
| ProjectPermissionManager.permissionDrawbacks[name].forEach(drawback => { | |
| string += `▪ ${drawback}\n`; | |
| }); | |
| let acceptCode = "ok"; | |
| if (ProjectPermissionManager.requiresCode.includes(name)) { | |
| acceptCode = ProjectPermissionManager.GenerateCode(6); | |
| }; | |
| string += `\nType "${acceptCode}" to allow, or type "stop" to never ask for this permission again.`; | |
| const allow = ProjectPermissionManager.EditPromptForAcceptCheck(prompt(string, "")); | |
| if (allow == "stop") { | |
| // yes this does intentionally disable asking for any specific website after one was rejected | |
| ProjectPermissionManager.disabledPermissions.push(name); | |
| return false; | |
| } | |
| const allowed = allow === String(acceptCode); | |
| if (name == "limitedWebsite") { | |
| if (!allowed) return false; | |
| ProjectPermissionManager.permissions.limitedWebsites[args[0]] = true; | |
| return true; | |
| }; | |
| ProjectPermissionManager.permissions[name] = allowed; | |
| return allowed; | |
| }; | |
| static RequestAllPermissions() { | |
| // packager | |
| if (ProjectPermissionManager.skipPermissionRequest === true) return true; | |
| if (ProjectPermissionManager.disabledPermissions.includes("all")) return false; | |
| const permissions = []; | |
| Object.getOwnPropertyNames(ProjectPermissionManager.permissions).forEach(permissionName => { | |
| if (typeof ProjectPermissionManager.permissions[permissionName] != "boolean") return; | |
| permissions.push(permissionName); | |
| }); | |
| let string = `Give all permissions to this project?`; | |
| string += `\n\nThis will allow the project to:\n`; | |
| permissions.forEach(permissionName => { | |
| ProjectPermissionManager.permissionDrawbacks[permissionName].forEach(drawback => { | |
| string += `▪ ${drawback}\n`; | |
| }); | |
| }); | |
| const acceptCode = ProjectPermissionManager.GenerateCode(8); | |
| string += `\nType "${acceptCode}" to allow, or type "stop" to never ask for all permissions again.`; | |
| const allow = ProjectPermissionManager.EditPromptForAcceptCheck(prompt(string, "")); | |
| if (allow == "stop") { | |
| ProjectPermissionManager.disabledPermissions.push("all"); | |
| return false; | |
| } | |
| const allowed = allow === String(acceptCode); | |
| if (!allowed) return false; | |
| Object.getOwnPropertyNames(ProjectPermissionManager.permissions).forEach(permissionName => { | |
| if (typeof ProjectPermissionManager.permissions[permissionName] != "boolean") return; | |
| ProjectPermissionManager.permissions[permissionName] = true; | |
| }); | |
| return true; | |
| } | |
| static CanCreateURLObject(url) { | |
| let success = true; | |
| try { | |
| new URL(url); | |
| } catch { | |
| success = false; | |
| } | |
| return success; | |
| } | |
| static IsDataUrl(url) { | |
| // if its not a valid url | |
| // its probably not a data url | |
| if (!this.CanCreateURLObject(url)) return false; | |
| // create url object cuz ez to read | |
| const urlObject = new URL(url); | |
| // now we can just check the protocol | |
| return urlObject.protocol === 'data:'; | |
| }; | |
| static IsUrlSafe(url) { // checks for non-kid friendly urls because that would be a big stinker | |
| // we dont know what this is just say yup thas good | |
| if (!this.CanCreateURLObject(url)) return false; | |
| // custom urls cannot be checked yet, just say its safe for now | |
| if (ProjectPermissionManager.IsDataUrl(url)) return true; | |
| const urlObject = new URL(url); | |
| const origin = urlObject.origin.toLowerCase(); | |
| // check origin for stuff | |
| let returningValue = true; | |
| // obviously this can be bypassed | |
| // but it blocks large or well-known sites | |
| // from working straight out of the gate | |
| // projects with these sites will not be approved anyways | |
| if ( | |
| origin.includes("xxx") | |
| || origin.includes("adult") | |
| || origin.includes(atob("c2V4")) | |
| || origin.includes(atob("cG9ybg==")) | |
| || origin.includes(atob("Ym9vcnU=")) | |
| || origin.includes(atob("aGVudGFp")) | |
| ) returningValue = false; | |
| // const mainName = link.match(/(?=(\.|\/\/))[^\n]+(?=(\.))/gmi)[0].replace(/(\/\/|)[^\n]+(?=(\.))/gmi, "").replace(/\/\//gmi, "") | |
| return returningValue; | |
| }; | |
| }; | |
| module.exports = ProjectPermissionManager; |