feat: migrate client-side database calls to secure server-side API endpoints

- Create secure server-side API endpoints for course data, marks, exercises, newsfeeds, submissions, and organization management
- Implement role-based permission checking using checkUserCoursePermissions utility
- Move all client-side Supabase calls to authenticated server endpoints in /api/courses/ and /api/org/
- Add proper authentication and authorization middleware via hooks.server.ts
- Update service functions to use getAccessToken() for API authentication
- Ensure data filtering based on user roles (students only see their own data)
- Maintain backward compatibility with existing component interfaces
This commit is contained in:
Rotimi Best
2025-12-05 10:48:01 +01:00
parent bf614fd782
commit ac4fdf1dd3
22 changed files with 986 additions and 200 deletions
@@ -91,7 +91,8 @@ export async function setCourse(data: Course, setLesson = true) {
// const tutorsById = {};
if (data.group) {
const groupData = Object.assign(data.group, {
const copiedGroup = JSON.parse(JSON.stringify(data.group));
const groupData = Object.assign(copiedGroup, {
tutors: [],
students: [],
people: []
@@ -8,7 +8,7 @@
import Confetti from '../Confetti/index.svelte';
import { isMobile } from '$lib/utils/store/useMobile';
import { profile } from '$lib/utils/store/user';
import { fetchCourse } from '$lib/utils/services/courses';
import { fetchCourseFromAPI } from '$lib/utils/services/courses';
import { globalStore } from '$lib/utils/store/app';
import { lessons } from '../Course/components/Lesson/store/lessons';
import Modal from '$lib/components/Modal/index.svelte';
@@ -32,7 +32,7 @@
course.set(defaultCourse);
lessons.set([]);
const { data: _data } = await fetchCourse(courseId);
const { data: _data } = await fetchCourseFromAPI(courseId);
if (_data) {
$course.type = _data.type;
@@ -52,7 +52,6 @@
$: onCourseIdChange(courseId);
$: {
console.log('isOrgAdmin', $isOrgAdmin);
const user = $group.people.find((person) => person.profile_id === $profile.id);
if (user) {
$globalStore.isStudent = user.role_id === 3;
@@ -3,6 +3,7 @@
import { group } from '../Course/store';
import type { GroupPerson } from '$lib/utils/types';
import { isOrgAdmin } from '$lib/utils/store/org';
import { browser } from '$app/environment';
export let allowedRoles: number[] = [];
export let onDenied = () => {};
@@ -17,19 +18,21 @@
}
$: {
const user: GroupPerson = $group.people.find((person) => person.profile_id === $profile.id)!;
if (browser) {
const user: GroupPerson = $group.people.find((person) => person.profile_id === $profile.id)!;
userRole = user ? user.role_id : userRole;
userRole = user ? user.role_id : userRole;
if (!$isOrgAdmin && $group.people.length && !isAllowed(userRole)) {
onDenied();
if (!$isOrgAdmin && $group.people.length && !isAllowed(userRole)) {
onDenied();
}
}
}
$: if (onlyStudent) {
show = isAllowed(userRole);
} else {
show = isAllowed(userRole) || $isOrgAdmin;
show = isAllowed(userRole) || !!$isOrgAdmin;
}
</script>