Spaces:
Running
Running
File size: 7,086 Bytes
30c32c8 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
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; |