fix: authorization bypass vulnerabilities in plan-restricted features
- Add plan validation to custom domain saving (Domains.svelte) - Add plan validation to certificate customization (Design.svelte) - Add plan validation to document upload (AddDocumentToLesson.svelte) - Add plan validation to video upload (UploadVideo.svelte) - Enhance team member function validation (TeamMembers.svelte) Prevents free users from bypassing UI restrictions via DOM manipulation. All restricted functions now enforce server-side plan validation.
This commit is contained in:
@@ -40,6 +40,12 @@
|
||||
isSaving = true;
|
||||
|
||||
try {
|
||||
// Prevent free plan users from bypassing UI restrictions
|
||||
if ($isFreePlan) {
|
||||
errors.description = 'Certificate customization is only available on paid plans';
|
||||
throw new Error(errors.description);
|
||||
}
|
||||
|
||||
const result = saveCertificateValidation({
|
||||
description: $course.description || '',
|
||||
is_certificate_downloadable: $course.is_certificate_downloadable || false,
|
||||
|
||||
+8
@@ -107,6 +107,14 @@
|
||||
|
||||
async function uploadDocument() {
|
||||
if (!selectedFile) return;
|
||||
|
||||
// Prevent free plan users from bypassing UI restrictions
|
||||
if ($isFreePlan) {
|
||||
$lessonDocUpload.error = $t('upgrade.required');
|
||||
snackbar.error($lessonDocUpload.error);
|
||||
return;
|
||||
}
|
||||
|
||||
$lessonDocUpload.isUploading = true;
|
||||
|
||||
try {
|
||||
|
||||
+11
@@ -30,6 +30,17 @@
|
||||
async function onUpload() {
|
||||
if (!fileInput) return;
|
||||
|
||||
// Prevent free plan users from bypassing UI restrictions
|
||||
if ($isFreePlan) {
|
||||
formRes = {
|
||||
type: 'AUTHORIZATION_ERROR',
|
||||
status: 403,
|
||||
message: $t('upgrade.required')
|
||||
};
|
||||
isLoaded = true;
|
||||
return;
|
||||
}
|
||||
|
||||
videoUploader.initUpload();
|
||||
|
||||
const videoFile = fileInput.files[0];
|
||||
|
||||
@@ -81,6 +81,12 @@
|
||||
async function handleSaveCustomDomain() {
|
||||
if (!isDomainValid) return;
|
||||
|
||||
// Prevent free plan users from bypassing UI restrictions
|
||||
if ($isFreePlan) {
|
||||
errors.customDomain = 'Custom domains are only available on paid plans';
|
||||
return;
|
||||
}
|
||||
|
||||
const sanitizedDomain = sanitizeDomain(customDomain);
|
||||
|
||||
const details = parse(sanitizedDomain);
|
||||
|
||||
@@ -30,6 +30,12 @@
|
||||
let isRemoving: number | null = null;
|
||||
|
||||
async function onSendInvite() {
|
||||
// Check if user is on free plan
|
||||
if ($isFreePlan) {
|
||||
snackbar.error('upgrade.required');
|
||||
return;
|
||||
}
|
||||
|
||||
const { hasError, error: _error, emails } = validateEmailInString(emailsStr);
|
||||
|
||||
if (hasError) {
|
||||
@@ -105,6 +111,12 @@
|
||||
}
|
||||
|
||||
async function onRemove(id: number) {
|
||||
// Check if user is on free plan
|
||||
if ($isFreePlan) {
|
||||
snackbar.error('upgrade.required');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('onRemove called');
|
||||
isRemoving = id;
|
||||
const { error } = await supabase.from('organizationmember').delete().match({ id });
|
||||
|
||||
Reference in New Issue
Block a user