mirror of
https://github.com/filecoin-project/slate.git
synced 2024-12-25 01:52:45 +03:00
305 lines
6.6 KiB
JavaScript
305 lines
6.6 KiB
JavaScript
import * as Strings from "~/common/strings";
|
|
import * as Constants from "~/common/constants";
|
|
|
|
import JSZip from "jszip";
|
|
|
|
const USERNAME_REGEX = new RegExp("^[a-zA-Z0-9_]{0,}[a-zA-Z]+[0-9]*$");
|
|
const MIN_PASSWORD_LENGTH = 8;
|
|
const EMAIL_REGEX = /^[\w.!#$%&'*+\/=?^_`{|}~-]+@[-a-zA-Z0-9_.]+?\.[a-zA-Z]{2,50}$/;
|
|
const CONTAINS_DIGIT_REGEX = /\d/;
|
|
const CONTAINS_UPPERCASE_REGEX = /[A-Z]/;
|
|
const CONTAINS_LOWERCASE_REGEX = /[a-z]/;
|
|
const CONTAINS_SYMBOL_REGEX = /[ !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~]/;
|
|
const PIN_REGEX = /^[0-9]{6}$/;
|
|
// const URL_REGEX = /(http(s)?:\/\/.)?(www.)?[-a-zA-Z0-9@:%._+~#=]{2,256}.[a-z]{2,6}\b([-a-zA-Z0-9@:%_+.~#?&\/=]*)/;
|
|
const IFRAMELY_URL_REGEX = /^https?:\/\//i;
|
|
|
|
// TODO(jim): Regex should cover some of this.
|
|
const REJECT_LIST = [
|
|
"..",
|
|
"$",
|
|
"#",
|
|
"_",
|
|
"_next",
|
|
"next",
|
|
"webpack",
|
|
"system",
|
|
"experience",
|
|
"root",
|
|
"www",
|
|
"website",
|
|
"index",
|
|
"api",
|
|
"public",
|
|
"static",
|
|
"admin",
|
|
"administrator",
|
|
"webmaster",
|
|
"download",
|
|
"downloads",
|
|
"403",
|
|
"404",
|
|
"500",
|
|
"maintenance",
|
|
"guidelines",
|
|
"updates",
|
|
"login",
|
|
"authenticate",
|
|
"sign-in",
|
|
"sign_in",
|
|
"signin",
|
|
"log-in",
|
|
"log_in",
|
|
"logout",
|
|
"terms",
|
|
"terms-of-service",
|
|
"community",
|
|
"privacy",
|
|
"reset-password",
|
|
"reset",
|
|
"logout",
|
|
"dashboard",
|
|
"analytics",
|
|
"data",
|
|
"timeout",
|
|
"please-dont-use-timeout",
|
|
"faqs",
|
|
"about",
|
|
"guide",
|
|
];
|
|
|
|
export const userRoute = (text) => {
|
|
if (!USERNAME_REGEX.test(text)) {
|
|
return false;
|
|
}
|
|
|
|
if (REJECT_LIST.includes(text)) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
export const slatename = (text) => {
|
|
if (Strings.isEmpty(text)) {
|
|
return false;
|
|
}
|
|
|
|
if (text.length > 48) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
export const username = (text) => {
|
|
if (Strings.isEmpty(text)) {
|
|
return false;
|
|
}
|
|
|
|
if (text.length > 48 || text.length < 1) {
|
|
return false;
|
|
}
|
|
|
|
if (!userRoute(text)) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
export const email = (text) => {
|
|
if (Strings.isEmpty(text)) {
|
|
return false;
|
|
}
|
|
|
|
if (text.length > 254 || text.length < 5) {
|
|
return false;
|
|
}
|
|
|
|
if (!EMAIL_REGEX.test(text)) {
|
|
return false;
|
|
}
|
|
|
|
//NOTE(toast): add this if the sendgrid plan is upgraded
|
|
// const sgEmailValidation = validateEmail({ email: text });
|
|
// if (sgEmailValidation.verdict !== "Valid") {
|
|
// return false;
|
|
// }
|
|
|
|
return true;
|
|
};
|
|
|
|
// NOTE(amine): used to validate old users password (currently only used in signin)
|
|
export const legacyPassword = (text) => {
|
|
if (Strings.isEmpty(text)) {
|
|
return false;
|
|
}
|
|
|
|
if (text.length < MIN_PASSWORD_LENGTH) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
export const passwordForm = (text) => {
|
|
const validations = {
|
|
validLength: false,
|
|
containsLowerCase: false,
|
|
containsUpperCase: false,
|
|
containsSymbol: false,
|
|
containsNumbers: false,
|
|
};
|
|
|
|
if (Strings.isEmpty(text)) return validations;
|
|
|
|
if (text.length >= MIN_PASSWORD_LENGTH) validations.validLength = true;
|
|
if (CONTAINS_DIGIT_REGEX.test(text)) validations.containsNumbers = true;
|
|
if (CONTAINS_LOWERCASE_REGEX.test(text)) validations.containsLowerCase = true;
|
|
if (CONTAINS_UPPERCASE_REGEX.test(text)) validations.containsUpperCase = true;
|
|
if (CONTAINS_SYMBOL_REGEX.test(text)) validations.containsSymbol = true;
|
|
|
|
return validations;
|
|
};
|
|
|
|
export const password = (text) => {
|
|
if (Strings.isEmpty(text)) {
|
|
return false;
|
|
}
|
|
|
|
if (text.length <= MIN_PASSWORD_LENGTH) {
|
|
return false;
|
|
}
|
|
|
|
let reqCount = 0;
|
|
|
|
if (CONTAINS_DIGIT_REGEX.test(text)) {
|
|
reqCount += 1;
|
|
}
|
|
if (CONTAINS_LOWERCASE_REGEX.test(text)) {
|
|
reqCount += 1;
|
|
}
|
|
if (CONTAINS_UPPERCASE_REGEX.test(text)) {
|
|
reqCount += 1;
|
|
}
|
|
if (CONTAINS_SYMBOL_REGEX.test(text)) {
|
|
reqCount += 1;
|
|
}
|
|
|
|
return reqCount === 4;
|
|
};
|
|
|
|
export const endsWithAny = (options, string = "") =>
|
|
options.some((option) => {
|
|
if (string) {
|
|
return string.endsWith(option);
|
|
} else {
|
|
return false;
|
|
}
|
|
});
|
|
|
|
export const verificationPin = (pin) => {
|
|
if (Strings.isEmpty(pin)) {
|
|
return false;
|
|
}
|
|
|
|
return PIN_REGEX.test(pin);
|
|
};
|
|
|
|
export const link = (text) => {
|
|
if (Strings.isEmpty(text)) {
|
|
return false;
|
|
}
|
|
|
|
if (text.length < 4) {
|
|
return false;
|
|
}
|
|
|
|
return IFRAMELY_URL_REGEX.test(text);
|
|
};
|
|
|
|
export const isPreviewableImage = (type = "") => {
|
|
if (type.startsWith("image/svg")) return false;
|
|
|
|
return type.startsWith("image/");
|
|
};
|
|
|
|
export const isGif = (type) => isPreviewableImage && type.startsWith("image/gif");
|
|
|
|
export const isImageType = (type = "") => {
|
|
return type.startsWith("image/");
|
|
};
|
|
|
|
export const isAudioType = (type = "") => {
|
|
return type.startsWith("audio/");
|
|
};
|
|
|
|
export const isVideoType = (type = "") => {
|
|
return type.startsWith("video/");
|
|
};
|
|
|
|
export const isPdfType = (type = "") => {
|
|
return type.startsWith("application/pdf");
|
|
};
|
|
|
|
export const isEpubType = (type = "") => {
|
|
return type.startsWith("application/epub");
|
|
};
|
|
|
|
export const isUnityType = (type = "") => {
|
|
return type === "application/unity";
|
|
};
|
|
|
|
export const is3dFile = (filename = "") => {
|
|
return endsWithAny(
|
|
[".stl", ".obj", ".fbx", ".blend", ".c4d", ".glb", ".dae", ".3ds", ".wrl"],
|
|
filename.toLowerCase()
|
|
);
|
|
};
|
|
|
|
export const isCodeFile = (filename = "") => {
|
|
return endsWithAny([".js"], filename.toLowerCase());
|
|
};
|
|
|
|
export const isFontFile = (fileName = "") => {
|
|
return endsWithAny([".ttf", ".otf", ".woff", ".woff2"], fileName.toLowerCase());
|
|
};
|
|
|
|
export const isMarkdown = (filename = "", type = "") => {
|
|
return filename.toLowerCase().endsWith(".md") || type.startsWith("text/plain");
|
|
};
|
|
|
|
export const isDocument = (fileName = "", type = "") =>
|
|
isMarkdown(fileName, type) || isPdfType(type) || isEpubType(type);
|
|
|
|
export const isUnityFile = async (file) => {
|
|
try {
|
|
const zip = new JSZip();
|
|
|
|
const contents = await zip.loadAsync(file);
|
|
const fileNames = Object.keys(contents.files);
|
|
|
|
// NOTE(daniel): every Unity game file will have this file
|
|
const isUnityLoaderFile = (fileName) =>
|
|
[/unityloader.js/i, /(.*)\.loader.js/i].some((item) => item.test(fileName));
|
|
|
|
return fileNames.some((file) => isUnityLoaderFile(file));
|
|
} catch (e) {
|
|
return false;
|
|
}
|
|
};
|
|
|
|
export const isNFTLink = (file) => {
|
|
let domain = file?.data?.link?.domain;
|
|
if (!domain) return false;
|
|
domain = domain.toLowerCase();
|
|
return Constants.NFTDomains.includes(domain);
|
|
};
|
|
const isLinkWithSource = (source) => (file) => file.isLink && file.source === source;
|
|
export const isTwitterLink = isLinkWithSource("Twitter");
|
|
export const isYoutubeLink = isLinkWithSource("YouTube");
|
|
export const isTwitchLink = isLinkWithSource("Twitch");
|
|
export const isGithubLink = isLinkWithSource("GitHub");
|
|
export const isInstagramLink = isLinkWithSource("Instagram");
|