├── services ├── node │ ├── .gitignore │ ├── config.json │ ├── model │ │ ├── faculties.js │ │ ├── degrees.js │ │ └── courses.js │ ├── package.json │ ├── verifyToken.js │ ├── service.js │ └── controller │ │ ├── facultyController.js │ │ └── degreeController.js └── spring-boot │ ├── af-zuulservice │ ├── src │ │ ├── test │ │ │ └── java │ │ │ │ ├── META-INF │ │ │ │ └── MANIFEST.MF │ │ │ │ └── net │ │ │ │ └── epiclanka │ │ │ │ └── acs │ │ │ │ └── AcsZuulserviceApplicationTests.java │ │ └── main │ │ │ ├── resources │ │ │ ├── application-cert.properties │ │ │ ├── application-dev.properties │ │ │ ├── application-prod.properties │ │ │ ├── application-stg.properties │ │ │ └── application.properties │ │ │ └── java │ │ │ └── net │ │ │ └── epiclanka │ │ │ └── acs │ │ │ └── AcsZuulserviceApplication.java │ ├── .mvn │ │ └── wrapper │ │ │ └── maven-wrapper.properties │ ├── .gitignore │ └── pom.xml │ ├── af-eurekaserver │ ├── src │ │ ├── test │ │ │ └── java │ │ │ │ ├── META-INF │ │ │ │ └── MANIFEST.MF │ │ │ │ └── net │ │ │ │ └── epiclanka │ │ │ │ └── acs │ │ │ │ └── AcsEurekaserverApplicationTests.java │ │ └── main │ │ │ ├── resources │ │ │ └── application.properties │ │ │ └── java │ │ │ └── net │ │ │ └── epiclanka │ │ │ └── acs │ │ │ └── AcsEurekaserverApplication.java │ ├── .mvn │ │ └── wrapper │ │ │ └── maven-wrapper.properties │ ├── .gitignore │ └── pom.xml │ ├── file-manage-service │ ├── .mvn │ │ └── wrapper │ │ │ ├── maven-wrapper.properties │ │ │ ├── maven-wrapper.jar │ │ │ └── MavenWrapperDownloader.java │ ├── src │ │ ├── main │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── sliit │ │ │ │ │ └── af │ │ │ │ │ ├── service │ │ │ │ │ ├── FileService.java │ │ │ │ │ └── impl │ │ │ │ │ │ └── FileServiceImpl.java │ │ │ │ │ ├── FileManageServiceApplication.java │ │ │ │ │ ├── exception │ │ │ │ │ ├── FileStorageException.java │ │ │ │ │ └── MyFileNotFoundException.java │ │ │ │ │ ├── aspect │ │ │ │ │ └── LoggingAspect.java │ │ │ │ │ ├── res │ │ │ │ │ └── UploadFileResponse.java │ │ │ │ │ └── controller │ │ │ │ │ └── FileController.java │ │ │ └── resources │ │ │ │ └── application.properties │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── sliit │ │ │ └── af │ │ │ └── filemanageservice │ │ │ └── FileManageServiceApplicationTests.java │ ├── .gitignore │ └── pom.xml │ └── student-information-service │ ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.properties │ │ ├── maven-wrapper.jar │ │ └── MavenWrapperDownloader.java │ ├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── sliit │ │ │ │ └── af │ │ │ │ ├── repository │ │ │ │ ├── RoleRepository.java │ │ │ │ └── UserRepository.java │ │ │ │ ├── service │ │ │ │ ├── EmailService.java │ │ │ │ ├── UserService.java │ │ │ │ └── impl │ │ │ │ │ └── EmailServiceImpl.java │ │ │ │ ├── domain │ │ │ │ └── UserDTO.java │ │ │ │ ├── StudentInformationServiceApplication.java │ │ │ │ ├── util │ │ │ │ ├── Param.java │ │ │ │ ├── OnRegistrationEvent.java │ │ │ │ └── ExceptionHandlerController.java │ │ │ │ ├── config │ │ │ │ ├── BeanConfig.java │ │ │ │ ├── WebConfig.java │ │ │ │ ├── JWTAuthorizationFilter.java │ │ │ │ ├── WebSecurity.java │ │ │ │ └── JWTAuthenticationFilter.java │ │ │ │ ├── model │ │ │ │ ├── Role.java │ │ │ │ ├── VerificationToken.java │ │ │ │ └── User.java │ │ │ │ ├── response │ │ │ │ └── ErrorResponse.java │ │ │ │ └── aspect │ │ │ │ └── LoggingAspect.java │ │ └── resources │ │ │ └── application.properties │ └── test │ │ └── java │ │ └── com │ │ └── sliit │ │ └── af │ │ └── studentinformationservice │ │ ├── controller │ │ └── UserControllerTests.java │ │ └── serviceTests │ │ └── UserServiceTests.java │ ├── .gitignore │ └── pom.xml └── client ├── src ├── components │ ├── SideNavigation.css │ ├── functions │ │ ├── config.json │ │ ├── Functions.js │ │ ├── StyledDropzone.js │ │ └── Services.js │ ├── pages │ │ ├── Home.js │ │ ├── Contact.css │ │ ├── About.css │ │ ├── CourseView.js │ │ ├── NotFoundPage.js │ │ ├── CourseEdit.js │ │ ├── sections │ │ │ ├── FacultyList.js │ │ │ ├── HomeBody.js │ │ │ ├── EventCalender.js │ │ │ ├── AssignmentView.js │ │ │ ├── AssignmentEdit.js │ │ │ ├── CourseBreadcrumSection.js │ │ │ ├── CourseMaterialsView.js │ │ │ ├── Announcements.js │ │ │ ├── MyCourses.js │ │ │ ├── AssignmentEditElement.js │ │ │ ├── CourseElement.js │ │ │ ├── SubmitAssignment.js │ │ │ └── CourseMaterials.js │ │ ├── DegreeList.js │ │ ├── SearchCourse.js │ │ ├── CourseList.js │ │ └── Profile.js │ ├── Footer.js │ ├── Routes.js │ ├── TopNavigation.js │ └── modals │ │ └── Login.js ├── images │ ├── SLIIT.png │ ├── avatar.png │ ├── login.png │ ├── sliit-walk.JPG │ └── SLIIT-malabe.jpg ├── App.test.js ├── index.js ├── App.js ├── logo.svg ├── index.css └── serviceWorker.js ├── build ├── favicon.ico ├── static │ ├── media │ │ ├── SLIIT.5c488492.png │ │ ├── Roboto-Bold.dc81817d.woff │ │ ├── Roboto-Bold.e31fcf18.ttf │ │ ├── Roboto-Bold.ecdd509c.eot │ │ ├── Roboto-Light.46e48ce0.ttf │ │ ├── Roboto-Light.a990f611.eot │ │ ├── Roboto-Thin.7500519d.woff │ │ ├── Roboto-Thin.94998475.ttf │ │ ├── Roboto-Thin.dfe56a87.eot │ │ ├── SLIIT-malabe.0b6863c8.jpg │ │ ├── fa-solid-900.e2675a61.eot │ │ ├── fa-solid-900.f14c3b2f.ttf │ │ ├── sliit-walk.644a5c22.JPG │ │ ├── Roboto-Bold.39b2c303.woff2 │ │ ├── Roboto-Light.3b813c2a.woff │ │ ├── Roboto-Light.69f8a061.woff2 │ │ ├── Roboto-Medium.4d9f3f9e.eot │ │ ├── Roboto-Medium.894a2ede.ttf │ │ ├── Roboto-Medium.fc78759e.woff │ │ ├── Roboto-Regular.30799efa.eot │ │ ├── Roboto-Regular.df7b648c.ttf │ │ ├── Roboto-Thin.954bbdeb.woff2 │ │ ├── fa-brands-400.8e49b728.eot │ │ ├── fa-brands-400.9f018d10.woff │ │ ├── fa-brands-400.b7d071b9.ttf │ │ ├── fa-regular-400.859001f6.eot │ │ ├── fa-regular-400.f3334251.ttf │ │ ├── fa-solid-900.0be94a07.woff │ │ ├── fa-solid-900.64b3e814.woff2 │ │ ├── Roboto-Medium.574fd0b5.woff2 │ │ ├── Roboto-Regular.2751ee43.woff2 │ │ ├── Roboto-Regular.ba3dcd89.woff │ │ ├── fa-brands-400.9f4ce3dc.woff2 │ │ ├── fa-regular-400.7980a636.woff2 │ │ ├── fa-regular-400.7aaf5675.woff │ │ ├── arrow_left.11911410.svg │ │ └── arrow_right.8ef6a08c.svg │ ├── js │ │ └── runtime~main.a8a9905a.js │ └── css │ │ └── main.e9c9038f.chunk.css ├── manifest.json ├── service-worker.js ├── asset-manifest.json └── index.html ├── public ├── favicon.ico ├── manifest.json └── index.html ├── .gitignore ├── package.json └── README.md /services/node/.gitignore: -------------------------------------------------------------------------------- 1 | /package-lock.json 2 | /node_modules 3 | 4 | -------------------------------------------------------------------------------- /services/node/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "secret":"af-final-2019" 3 | } 4 | -------------------------------------------------------------------------------- /client/src/components/SideNavigation.css: -------------------------------------------------------------------------------- 1 | ::-webkit-scrollbar { 2 | display: none; 3 | } -------------------------------------------------------------------------------- /services/spring-boot/af-zuulservice/src/test/java/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Class-Path: 3 | 4 | -------------------------------------------------------------------------------- /services/spring-boot/af-eurekaserver/src/test/java/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Class-Path: 3 | 4 | -------------------------------------------------------------------------------- /client/build/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/build/favicon.ico -------------------------------------------------------------------------------- /client/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/public/favicon.ico -------------------------------------------------------------------------------- /client/src/images/SLIIT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/src/images/SLIIT.png -------------------------------------------------------------------------------- /client/src/images/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/src/images/avatar.png -------------------------------------------------------------------------------- /client/src/images/login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/src/images/login.png -------------------------------------------------------------------------------- /client/src/images/sliit-walk.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/src/images/sliit-walk.JPG -------------------------------------------------------------------------------- /client/src/images/SLIIT-malabe.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/src/images/SLIIT-malabe.jpg -------------------------------------------------------------------------------- /client/build/static/media/SLIIT.5c488492.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/build/static/media/SLIIT.5c488492.png -------------------------------------------------------------------------------- /services/spring-boot/af-eurekaserver/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.4/apache-maven-3.5.4-bin.zip 2 | -------------------------------------------------------------------------------- /services/spring-boot/af-zuulservice/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.4/apache-maven-3.5.4-bin.zip 2 | -------------------------------------------------------------------------------- /client/build/static/media/Roboto-Bold.dc81817d.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/build/static/media/Roboto-Bold.dc81817d.woff -------------------------------------------------------------------------------- /client/build/static/media/Roboto-Bold.e31fcf18.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/build/static/media/Roboto-Bold.e31fcf18.ttf -------------------------------------------------------------------------------- /client/build/static/media/Roboto-Bold.ecdd509c.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/build/static/media/Roboto-Bold.ecdd509c.eot -------------------------------------------------------------------------------- /client/build/static/media/Roboto-Light.46e48ce0.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/build/static/media/Roboto-Light.46e48ce0.ttf -------------------------------------------------------------------------------- /client/build/static/media/Roboto-Light.a990f611.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/build/static/media/Roboto-Light.a990f611.eot -------------------------------------------------------------------------------- /client/build/static/media/Roboto-Thin.7500519d.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/build/static/media/Roboto-Thin.7500519d.woff -------------------------------------------------------------------------------- /client/build/static/media/Roboto-Thin.94998475.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/build/static/media/Roboto-Thin.94998475.ttf -------------------------------------------------------------------------------- /client/build/static/media/Roboto-Thin.dfe56a87.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/build/static/media/Roboto-Thin.dfe56a87.eot -------------------------------------------------------------------------------- /client/build/static/media/SLIIT-malabe.0b6863c8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/build/static/media/SLIIT-malabe.0b6863c8.jpg -------------------------------------------------------------------------------- /client/build/static/media/fa-solid-900.e2675a61.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/build/static/media/fa-solid-900.e2675a61.eot -------------------------------------------------------------------------------- /client/build/static/media/fa-solid-900.f14c3b2f.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/build/static/media/fa-solid-900.f14c3b2f.ttf -------------------------------------------------------------------------------- /client/build/static/media/sliit-walk.644a5c22.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/build/static/media/sliit-walk.644a5c22.JPG -------------------------------------------------------------------------------- /client/src/components/functions/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodeBaseUrl": "http://192.168.43.98:4000", 3 | "springBaseUrl": "http://localhost:9090", 4 | "fileService": "http://localhost:9091" 5 | } -------------------------------------------------------------------------------- /client/build/static/media/Roboto-Bold.39b2c303.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/build/static/media/Roboto-Bold.39b2c303.woff2 -------------------------------------------------------------------------------- /client/build/static/media/Roboto-Light.3b813c2a.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/build/static/media/Roboto-Light.3b813c2a.woff -------------------------------------------------------------------------------- /client/build/static/media/Roboto-Light.69f8a061.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/build/static/media/Roboto-Light.69f8a061.woff2 -------------------------------------------------------------------------------- /client/build/static/media/Roboto-Medium.4d9f3f9e.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/build/static/media/Roboto-Medium.4d9f3f9e.eot -------------------------------------------------------------------------------- /client/build/static/media/Roboto-Medium.894a2ede.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/build/static/media/Roboto-Medium.894a2ede.ttf -------------------------------------------------------------------------------- /client/build/static/media/Roboto-Medium.fc78759e.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/build/static/media/Roboto-Medium.fc78759e.woff -------------------------------------------------------------------------------- /client/build/static/media/Roboto-Regular.30799efa.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/build/static/media/Roboto-Regular.30799efa.eot -------------------------------------------------------------------------------- /client/build/static/media/Roboto-Regular.df7b648c.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/build/static/media/Roboto-Regular.df7b648c.ttf -------------------------------------------------------------------------------- /client/build/static/media/Roboto-Thin.954bbdeb.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/build/static/media/Roboto-Thin.954bbdeb.woff2 -------------------------------------------------------------------------------- /client/build/static/media/fa-brands-400.8e49b728.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/build/static/media/fa-brands-400.8e49b728.eot -------------------------------------------------------------------------------- /client/build/static/media/fa-brands-400.9f018d10.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/build/static/media/fa-brands-400.9f018d10.woff -------------------------------------------------------------------------------- /client/build/static/media/fa-brands-400.b7d071b9.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/build/static/media/fa-brands-400.b7d071b9.ttf -------------------------------------------------------------------------------- /client/build/static/media/fa-regular-400.859001f6.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/build/static/media/fa-regular-400.859001f6.eot -------------------------------------------------------------------------------- /client/build/static/media/fa-regular-400.f3334251.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/build/static/media/fa-regular-400.f3334251.ttf -------------------------------------------------------------------------------- /client/build/static/media/fa-solid-900.0be94a07.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/build/static/media/fa-solid-900.0be94a07.woff -------------------------------------------------------------------------------- /client/build/static/media/fa-solid-900.64b3e814.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/build/static/media/fa-solid-900.64b3e814.woff2 -------------------------------------------------------------------------------- /services/spring-boot/file-manage-service/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip 2 | -------------------------------------------------------------------------------- /client/build/static/media/Roboto-Medium.574fd0b5.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/build/static/media/Roboto-Medium.574fd0b5.woff2 -------------------------------------------------------------------------------- /client/build/static/media/Roboto-Regular.2751ee43.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/build/static/media/Roboto-Regular.2751ee43.woff2 -------------------------------------------------------------------------------- /client/build/static/media/Roboto-Regular.ba3dcd89.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/build/static/media/Roboto-Regular.ba3dcd89.woff -------------------------------------------------------------------------------- /client/build/static/media/fa-brands-400.9f4ce3dc.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/build/static/media/fa-brands-400.9f4ce3dc.woff2 -------------------------------------------------------------------------------- /client/build/static/media/fa-regular-400.7980a636.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/build/static/media/fa-regular-400.7980a636.woff2 -------------------------------------------------------------------------------- /client/build/static/media/fa-regular-400.7aaf5675.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/client/build/static/media/fa-regular-400.7aaf5675.woff -------------------------------------------------------------------------------- /services/spring-boot/student-information-service/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip 2 | -------------------------------------------------------------------------------- /services/spring-boot/file-manage-service/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/services/spring-boot/file-manage-service/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /services/spring-boot/student-information-service/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ranmal-Dewage/Student-and-Instructor-Information-System/HEAD/services/spring-boot/student-information-service/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /client/build/static/media/arrow_left.11911410.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /client/build/static/media/arrow_right.8ef6a08c.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /client/src/components/functions/Functions.js: -------------------------------------------------------------------------------- 1 | export function getHash(str) { 2 | let hash = 0 3 | for (let i = 0; i < str.length; i++) { 4 | hash += Math.pow(str.charCodeAt(i) * 31, str.length - i) 5 | hash = hash & hash // Convert to 32bit integer 6 | } 7 | return JSON.stringify(hash) 8 | }; -------------------------------------------------------------------------------- /client/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | ReactDOM.unmountComponentAtNode(div); 9 | }); 10 | -------------------------------------------------------------------------------- /services/node/model/faculties.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | 3 | let facultiesSchema = mongoose.Schema({ 4 | fname: String, 5 | fcode: String, 6 | description: String 7 | }); 8 | 9 | const Faculties = mongoose.model('Faculties', facultiesSchema); 10 | 11 | module.exports = Faculties; 12 | -------------------------------------------------------------------------------- /client/src/components/pages/Home.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import HomeBody from './sections/HomeBody'; 3 | 4 | export default class Home extends React.Component { 5 | render() { 6 | return ( 7 | 8 | 9 | 10 | ) 11 | } 12 | } -------------------------------------------------------------------------------- /services/node/model/degrees.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose") 2 | 3 | let degreesSchema = mongoose.Schema({ 4 | dname: String, 5 | dcode: String, 6 | duration: String, 7 | price: Number, 8 | fcode: String 9 | }) 10 | 11 | const Degrees = mongoose.model("Degrees", degreesSchema) 12 | 13 | module.exports = Degrees 14 | -------------------------------------------------------------------------------- /client/build/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /client/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /services/spring-boot/af-eurekaserver/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=AF-Eureka-Server 2 | server.port=8761 3 | eureka.client.register-with-eureka=false 4 | eureka.client.fetch-registry=false 5 | eureka.server.enable-self-preservation=true 6 | eureka.server.eviction-interval-timer-in-ms=1000 7 | 8 | eureka.instance.securePort: ${server.port} 9 | eureka.instance.securePortEnabled: true -------------------------------------------------------------------------------- /services/spring-boot/file-manage-service/src/main/java/com/sliit/af/service/FileService.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.sliit.af.service; 5 | 6 | import org.springframework.core.io.Resource; 7 | import org.springframework.web.multipart.MultipartFile; 8 | 9 | /** 10 | * @author vimukthi_r 11 | * 12 | */ 13 | public interface FileService { 14 | public String storeFile(MultipartFile file); 15 | 16 | public Resource loadFileAsResource(String fileName); 17 | } 18 | -------------------------------------------------------------------------------- /services/spring-boot/file-manage-service/src/main/java/com/sliit/af/FileManageServiceApplication.java: -------------------------------------------------------------------------------- 1 | package com.sliit.af; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class FileManageServiceApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(FileManageServiceApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /services/spring-boot/file-manage-service/src/main/java/com/sliit/af/exception/FileStorageException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.sliit.af.exception; 5 | 6 | /** 7 | * @author vimukthi_r 8 | * 9 | */ 10 | public class FileStorageException extends RuntimeException { 11 | 12 | /** 13 | * 14 | */ 15 | private static final long serialVersionUID = 8878771581626075766L; 16 | 17 | public FileStorageException(String message) { 18 | super(message); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /client/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | import * as serviceWorker from './serviceWorker'; 5 | 6 | ReactDOM.render(, document.getElementById('root')); 7 | 8 | // If you want your app to work offline and load faster, you can change 9 | // unregister() to register() below. Note this comes with some pitfalls. 10 | // Learn more about service workers: https://bit.ly/CRA-PWA 11 | serviceWorker.unregister(); 12 | -------------------------------------------------------------------------------- /services/spring-boot/file-manage-service/src/main/java/com/sliit/af/exception/MyFileNotFoundException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.sliit.af.exception; 5 | 6 | /** 7 | * @author vimukthi_r 8 | * 9 | */ 10 | public class MyFileNotFoundException extends RuntimeException { 11 | 12 | /** 13 | * 14 | */ 15 | private static final long serialVersionUID = 8878771581626075766L; 16 | 17 | public MyFileNotFoundException(String message) { 18 | super(message); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /client/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | #/build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | 25 | /.idea 26 | /.cache 27 | 28 | # webstorm 29 | /node_modules -------------------------------------------------------------------------------- /services/node/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-js", 3 | "version": "1.0.0", 4 | "description": "SIIS Node JS Backend", 5 | "main": "service.js", 6 | "scripts": { 7 | "start": "node ./service.js" 8 | }, 9 | "author": "Viking Raiders", 10 | "license": "ISC", 11 | "dependencies": { 12 | "cors": "^2.8.5", 13 | "express": "^4.17.1", 14 | "jsonwebtoken": "^8.5.1", 15 | "mongoose": "^5.6.0", 16 | "node-fetch": "^2.6.0", 17 | "nodemailer": "^6.2.1" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /services/spring-boot/af-zuulservice/src/test/java/net/epiclanka/acs/AcsZuulserviceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package net.epiclanka.acs; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class AcsZuulserviceApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /services/spring-boot/af-eurekaserver/src/test/java/net/epiclanka/acs/AcsEurekaserverApplicationTests.java: -------------------------------------------------------------------------------- 1 | package net.epiclanka.acs; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class AcsEurekaserverApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /services/spring-boot/file-manage-service/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/** 5 | !**/src/test/** 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | 30 | ### VS Code ### 31 | .vscode/ 32 | 33 | output.log 34 | -------------------------------------------------------------------------------- /services/spring-boot/file-manage-service/src/test/java/com/sliit/af/filemanageservice/FileManageServiceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.sliit.af.filemanageservice; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class FileManageServiceApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /services/spring-boot/student-information-service/src/main/java/com/sliit/af/repository/RoleRepository.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.sliit.af.repository; 5 | 6 | import java.util.Optional; 7 | 8 | import org.springframework.data.mongodb.repository.MongoRepository; 9 | 10 | import com.sliit.af.model.Role; 11 | 12 | /** 13 | * @author Vimukthi Rajapaksha 14 | * @date Apr 15, 2019 15 | */ 16 | public interface RoleRepository extends MongoRepository { 17 | 18 | public Optional findByRole(String role); 19 | } 20 | -------------------------------------------------------------------------------- /services/spring-boot/student-information-service/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/** 5 | !**/src/test/** 6 | output.log 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | 17 | ### IntelliJ IDEA ### 18 | .idea 19 | *.iws 20 | *.iml 21 | *.ipr 22 | 23 | ### NetBeans ### 24 | /nbproject/private/ 25 | /nbbuild/ 26 | /dist/ 27 | /nbdist/ 28 | /.nb-gradle/ 29 | build/ 30 | 31 | ### VS Code ### 32 | .vscode/ 33 | -------------------------------------------------------------------------------- /services/spring-boot/student-information-service/src/main/java/com/sliit/af/service/EmailService.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.sliit.af.service; 5 | 6 | import org.springframework.context.ApplicationListener; 7 | 8 | import com.sliit.af.util.OnRegistrationEvent; 9 | 10 | /** 11 | * @author vimukthi_r 12 | * @Date Apr 29, 2019 13 | * @Description 14 | * @Version 15 | */ 16 | public interface EmailService extends ApplicationListener { 17 | public void sendEmail(String to, String subject, String text); 18 | } 19 | -------------------------------------------------------------------------------- /services/spring-boot/af-eurekaserver/src/main/java/net/epiclanka/acs/AcsEurekaserverApplication.java: -------------------------------------------------------------------------------- 1 | package net.epiclanka.acs; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; 6 | 7 | @SpringBootApplication 8 | @EnableEurekaServer 9 | public class AcsEurekaserverApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(AcsEurekaserverApplication.class, args); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /services/spring-boot/student-information-service/src/main/java/com/sliit/af/domain/UserDTO.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.sliit.af.domain; 5 | 6 | import javax.validation.constraints.NotBlank; 7 | 8 | import lombok.AllArgsConstructor; 9 | import lombok.Data; 10 | import lombok.NoArgsConstructor; 11 | 12 | /** 13 | * @author Vimukthi Rajapaksha 14 | * @date Apr 28, 2019 15 | */ 16 | @Data 17 | @AllArgsConstructor 18 | @NoArgsConstructor 19 | public class UserDTO { 20 | @NotBlank 21 | private String email; 22 | @NotBlank 23 | private String password; 24 | } 25 | -------------------------------------------------------------------------------- /services/node/verifyToken.js: -------------------------------------------------------------------------------- 1 | //verify token middleware 2 | //format 3 | //Authorization: Bearer 4 | function verifyToken(req, res, next) { 5 | 6 | const bearerHeader = req.headers["authorization"] 7 | if (typeof bearerHeader !== "undefined") { 8 | const bearer = bearerHeader.split(" ") 9 | const bearerToken = bearer[1] 10 | req.token = bearerToken 11 | next() //next middleware to avoid timeout server 12 | } else { 13 | res.status(403).json({ status: "forbidden" }) //forbidden 14 | 15 | } 16 | 17 | } 18 | 19 | module.exports = { verifyToken: verifyToken } 20 | -------------------------------------------------------------------------------- /services/spring-boot/af-zuulservice/src/main/resources/application-cert.properties: -------------------------------------------------------------------------------- 1 | #Zuul server port 2 | server.port=8084 3 | 4 | #Spring configurations 5 | spring.application.name=EcsAPIGateway 6 | eureka.client.serviceUrl.defaultZone:http://localhost:8761/eureka 7 | eureka.instance.prefer-ip-address=true 8 | 9 | #Zuul configurations 10 | zuul.routes.v1.serviceId=Acs-Auth-Handler 11 | zuul.routes.v2.serviceId=acs-challenge-handler 12 | zuul.host.socket-timeout-millis=30000 13 | 14 | #Eureka configurations 15 | eureka.instance.lease-renewal-interval-in-seconds=1 16 | eureka.instance.lease-expiration-duration-in-seconds=2 -------------------------------------------------------------------------------- /services/spring-boot/af-zuulservice/src/main/resources/application-dev.properties: -------------------------------------------------------------------------------- 1 | #Zuul server port 2 | server.port=8084 3 | 4 | #Spring configurations 5 | spring.application.name=EcsAPIGateway 6 | eureka.client.serviceUrl.defaultZone:http://localhost:8761/eureka 7 | eureka.instance.prefer-ip-address=true 8 | 9 | #Zuul configurations 10 | zuul.routes.v1.serviceId=Acs-Auth-Handler 11 | zuul.routes.v2.serviceId=acs-challenge-handler 12 | zuul.host.socket-timeout-millis=30000 13 | 14 | #Eureka configurations 15 | eureka.instance.lease-renewal-interval-in-seconds=1 16 | eureka.instance.lease-expiration-duration-in-seconds=2 -------------------------------------------------------------------------------- /services/spring-boot/af-zuulservice/src/main/resources/application-prod.properties: -------------------------------------------------------------------------------- 1 | #Zuul server port 2 | server.port=8084 3 | 4 | #Spring configurations 5 | spring.application.name=EcsAPIGateway 6 | eureka.client.serviceUrl.defaultZone:http://localhost:8761/eureka 7 | eureka.instance.prefer-ip-address=true 8 | 9 | #Zuul configurations 10 | zuul.routes.v1.serviceId=Acs-Auth-Handler 11 | zuul.routes.v2.serviceId=acs-challenge-handler 12 | zuul.host.socket-timeout-millis=30000 13 | 14 | #Eureka configurations 15 | eureka.instance.lease-renewal-interval-in-seconds=1 16 | eureka.instance.lease-expiration-duration-in-seconds=2 -------------------------------------------------------------------------------- /services/spring-boot/af-zuulservice/src/main/resources/application-stg.properties: -------------------------------------------------------------------------------- 1 | #Zuul server port 2 | server.port=8084 3 | 4 | #Spring configurations 5 | spring.application.name=EcsAPIGateway 6 | eureka.client.serviceUrl.defaultZone:http://localhost:8761/eureka 7 | eureka.instance.prefer-ip-address=true 8 | 9 | #Zuul configurations 10 | zuul.routes.v1.serviceId=Acs-Auth-Handler 11 | zuul.routes.v2.serviceId=acs-challenge-handler 12 | zuul.host.socket-timeout-millis=30000 13 | 14 | #Eureka configurations 15 | eureka.instance.lease-renewal-interval-in-seconds=1 16 | eureka.instance.lease-expiration-duration-in-seconds=2 -------------------------------------------------------------------------------- /services/spring-boot/student-information-service/src/main/java/com/sliit/af/StudentInformationServiceApplication.java: -------------------------------------------------------------------------------- 1 | package com.sliit.af; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.scheduling.annotation.EnableAsync; 6 | 7 | import springfox.documentation.swagger2.annotations.EnableSwagger2; 8 | 9 | @SpringBootApplication 10 | @EnableAsync 11 | @EnableSwagger2 12 | public class StudentInformationServiceApplication { 13 | 14 | public static void main(String[] args) { 15 | SpringApplication.run(StudentInformationServiceApplication.class, args); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /services/spring-boot/file-manage-service/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=9091 2 | 3 | ## MULTIPART (MultipartProperties) 4 | # Enable multipart uploads 5 | spring.servlet.multipart.enabled=true 6 | # Threshold after which files are written to disk. 7 | spring.servlet.multipart.file-size-threshold=2KB 8 | # Max file size. 9 | spring.servlet.multipart.max-file-size=200MB 10 | # Max Request Size 11 | spring.servlet.multipart.max-request-size=215MB 12 | 13 | ## File Storage Properties 14 | # All files uploaded through the REST API will be stored in this directory 15 | file.upload-dir=./uploads 16 | 17 | #logging 18 | logging.level.com.af2018.backend=DEBUG 19 | logging.file=output.log -------------------------------------------------------------------------------- /services/spring-boot/student-information-service/src/main/java/com/sliit/af/repository/UserRepository.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.sliit.af.repository; 5 | 6 | import java.util.Optional; 7 | 8 | import org.springframework.data.mongodb.repository.MongoRepository; 9 | 10 | import com.sliit.af.model.User; 11 | 12 | /** 13 | * @author Vimukthi Rajapaksha 14 | * @date Apr 15, 2019 15 | */ 16 | public interface UserRepository extends MongoRepository { 17 | public Optional findByEmailAndPassword(String email, String password); 18 | 19 | public Optional findByEmail(String email); 20 | 21 | public Optional findByVerificationTokenToken(String token); 22 | } 23 | -------------------------------------------------------------------------------- /services/spring-boot/af-zuulservice/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | #Zuul server port 2 | server.port=8097 3 | 4 | #Spring configurations 5 | spring.application.name=AF-API-Gateway 6 | eureka.client.serviceUrl.defaultZone:https://localhost:8761/eureka 7 | eureka.instance.prefer-ip-address=true 8 | 9 | #Zuul configurations 10 | zuul.routes.v1.serviceId=file-manager-service 11 | zuul.routes.v2.serviceId=acs-challenge-handler 12 | zuul.host.socket-timeout-millis=30000 13 | 14 | #Eureka configurations 15 | eureka.instance.lease-renewal-interval-in-seconds=1 16 | eureka.instance.lease-expiration-duration-in-seconds=2 17 | eureka.instance.securePortEnabled=true 18 | eureka.instance.nonSecurePortEnabled=false 19 | 20 | -------------------------------------------------------------------------------- /services/node/model/courses.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose") 2 | 3 | let coursesSchema = mongoose.Schema({ 4 | cname: String, 5 | ccode: String, 6 | description: String, 7 | credits: Number, 8 | fcode: String, 9 | dcode: String, 10 | year: String, 11 | semester: String, 12 | accept: Boolean, //for instructor notification purpose 13 | cmaterials: [{ fileName: String, fileDownloadUri: String, fileType: String, size: String }], 14 | assignments: [{ topic: String, description: String, dueDate: String, data: [{ fileName: String, fileDownloadUri: String, fileType: String, size: String }] }] 15 | }) 16 | 17 | const Courses = mongoose.model("Courses", coursesSchema) 18 | 19 | module.exports = Courses 20 | -------------------------------------------------------------------------------- /services/spring-boot/student-information-service/src/main/java/com/sliit/af/util/Param.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.sliit.af.util; 5 | 6 | /** 7 | * @author vimukthi_r 8 | * 9 | */ 10 | public class Param { 11 | private Param() { 12 | } 13 | 14 | // this secret key is used for json web token signing 15 | public static final String SECRET = "af-final-2019"; 16 | public static final String TOKEN_PREFIX = "Bearer "; 17 | public static final String HEADER_STRING = "Authorization"; 18 | public static final long EXPIRATION_TIME = 2_400_000; // 40 minutes 19 | 20 | public static final String ADMIN = "ADMIN"; 21 | public static final String INSTRUCTOR = "INSTRUCTOR"; 22 | public static final String STUDENT = "STUDENT"; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /services/spring-boot/student-information-service/src/main/java/com/sliit/af/config/BeanConfig.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.sliit.af.config; 5 | 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 9 | import org.springframework.web.client.RestTemplate; 10 | 11 | /** 12 | * @author Vimukthi Rajapaksha 13 | * @date Apr 28, 2019 14 | */ 15 | @Configuration 16 | public class BeanConfig { 17 | 18 | @Bean 19 | public BCryptPasswordEncoder bCryptPasswordEncoder() { 20 | return new BCryptPasswordEncoder(); 21 | } 22 | 23 | @Bean 24 | public RestTemplate restTemplate() { 25 | return new RestTemplate(); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /services/spring-boot/af-eurekaserver/.gitignore: -------------------------------------------------------------------------------- 1 | .metadata 2 | bin/ 3 | tmp/ 4 | *.tmp 5 | *.bak 6 | *.swp 7 | *~.nib 8 | local.properties 9 | .loadpath 10 | 11 | 12 | # eclipse project file 13 | .settings/ 14 | .classpath 15 | .project 16 | 17 | # Maven 18 | target/ 19 | 20 | # External tool builders 21 | .externalToolBuilders/ 22 | 23 | # Locally stored "Eclipse launch configurations" 24 | *.launch 25 | 26 | # STS (Spring Tool Suite) 27 | .springBeans 28 | 29 | # Code Recommenders 30 | .recommenders/ 31 | 32 | # Annotation Processing 33 | .apt_generated/ 34 | 35 | #Temp files generated at the build time 36 | *dependency-reduced-pom.xml 37 | 38 | # Binaries 39 | *.7z 40 | *.dmg 41 | *.gz 42 | *.iso 43 | *.jar 44 | *.rar 45 | *.tar 46 | *.zip 47 | *.war 48 | *.ear 49 | *.sar 50 | *.class -------------------------------------------------------------------------------- /services/spring-boot/af-zuulservice/.gitignore: -------------------------------------------------------------------------------- 1 | .metadata 2 | bin/ 3 | tmp/ 4 | *.tmp 5 | *.bak 6 | *.swp 7 | *~.nib 8 | local.properties 9 | .loadpath 10 | 11 | 12 | # eclipse project file 13 | .settings/ 14 | .classpath 15 | .project 16 | 17 | # Maven 18 | target/ 19 | 20 | # External tool builders 21 | .externalToolBuilders/ 22 | 23 | # Locally stored "Eclipse launch configurations" 24 | *.launch 25 | 26 | # STS (Spring Tool Suite) 27 | .springBeans 28 | 29 | # Code Recommenders 30 | .recommenders/ 31 | 32 | # Annotation Processing 33 | .apt_generated/ 34 | 35 | #Temp files generated at the build time 36 | *dependency-reduced-pom.xml 37 | 38 | # Binaries 39 | *.7z 40 | *.dmg 41 | *.gz 42 | *.iso 43 | *.jar 44 | *.rar 45 | *.tar 46 | *.zip 47 | *.war 48 | *.ear 49 | *.sar 50 | *.class -------------------------------------------------------------------------------- /client/src/components/pages/Contact.css: -------------------------------------------------------------------------------- 1 | .top-diagonal { 2 | position: relative; 3 | width: 100%; 4 | height: 50px; 5 | overflow: hidden; 6 | } 7 | 8 | .top-diagonal::before { 9 | content: ""; 10 | position: absolute; 11 | top: 0; 12 | width: 50%; 13 | height: 100%; 14 | background-color: #2bbbad; 15 | background-size: 200%, 0; 16 | transform: skewY(5deg); 17 | transform-origin: bottom right; 18 | } 19 | 20 | .top-diagonal::after { 21 | content: ""; 22 | position: absolute; 23 | top: 0; 24 | width: 50%; 25 | height: 100%; 26 | left: 50%; 27 | background-color: #2bbbad; 28 | background-size: 200%, 0; 29 | background-position: -100% 0; 30 | transform: skewY(-5deg); 31 | transform-origin: bottom left; 32 | } 33 | 34 | -------------------------------------------------------------------------------- /client/src/components/pages/About.css: -------------------------------------------------------------------------------- 1 | .about-top-diagonal { 2 | position: relative; 3 | width: 100%; 4 | height: 50px; 5 | overflow: hidden; 6 | } 7 | 8 | .about-top-diagonal::before { 9 | content: ""; 10 | position: absolute; 11 | top: 0; 12 | width: 50%; 13 | height: 100%; 14 | background-color: #2196f3; 15 | background-size: 200%, 0; 16 | transform: skewY(5deg); 17 | transform-origin: bottom right; 18 | } 19 | 20 | .about-top-diagonal::after { 21 | content: ""; 22 | position: absolute; 23 | top: 0; 24 | width: 50%; 25 | height: 100%; 26 | left: 50%; 27 | background-color: #2196f3; 28 | background-size: 200%, 0; 29 | background-position: -100% 0; 30 | transform: skewY(-5deg); 31 | transform-origin: bottom left; 32 | } 33 | 34 | -------------------------------------------------------------------------------- /services/spring-boot/student-information-service/src/main/java/com/sliit/af/util/OnRegistrationEvent.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.sliit.af.util; 5 | 6 | import org.springframework.context.ApplicationEvent; 7 | 8 | import com.sliit.af.model.User; 9 | 10 | import lombok.Getter; 11 | import lombok.Setter; 12 | 13 | /** 14 | * @author vimukthi_r 15 | * 16 | */ 17 | @Getter 18 | @Setter 19 | public class OnRegistrationEvent extends ApplicationEvent { 20 | 21 | /** 22 | * 23 | */ 24 | private static final long serialVersionUID = 8329608698733437942L; 25 | 26 | private User user; 27 | 28 | /** 29 | * @param source 30 | * @param appUrl 31 | * @param locale 32 | * @param user 33 | */ 34 | public OnRegistrationEvent(Object source, User user) { 35 | super(source); 36 | this.user = user; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /services/spring-boot/af-zuulservice/src/main/java/net/epiclanka/acs/AcsZuulserviceApplication.java: -------------------------------------------------------------------------------- 1 | package net.epiclanka.acs; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; 6 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 7 | import org.springframework.cloud.netflix.zuul.EnableZuulProxy; 8 | import org.springframework.cloud.openfeign.EnableFeignClients; 9 | 10 | @EnableFeignClients 11 | @EnableCircuitBreaker 12 | @SpringBootApplication 13 | @EnableZuulProxy 14 | @EnableDiscoveryClient 15 | public class AcsZuulserviceApplication { 16 | 17 | public static void main(String[] args) { 18 | SpringApplication.run(AcsZuulserviceApplication.class, args); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /services/spring-boot/student-information-service/src/main/java/com/sliit/af/model/Role.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.sliit.af.model; 5 | 6 | import javax.validation.constraints.NotBlank; 7 | import javax.validation.constraints.Pattern; 8 | 9 | import org.springframework.data.annotation.Id; 10 | import org.springframework.data.mongodb.core.index.Indexed; 11 | import org.springframework.data.mongodb.core.mapping.Document; 12 | 13 | import lombok.AllArgsConstructor; 14 | import lombok.Data; 15 | import lombok.NoArgsConstructor; 16 | 17 | /** 18 | * @author vimukthi_r 19 | * 20 | */ 21 | @Document(collection = "role") 22 | @Data 23 | @NoArgsConstructor 24 | @AllArgsConstructor 25 | public class Role { 26 | @Id 27 | private String id; 28 | @Indexed 29 | @NotBlank 30 | @Pattern(regexp="ADMIN|INSTRUCTOR|STUDENT") 31 | private String role; 32 | } 33 | -------------------------------------------------------------------------------- /client/src/components/Footer.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { MDBFooter, MDBIcon } from 'mdbreact'; 3 | 4 | const Footer = () => { 5 | return ( 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 |
14 |

15 | © {new Date().getFullYear()} Copyright: Viking Raiders 16 |

17 |
18 | ); 19 | } 20 | 21 | export default Footer; -------------------------------------------------------------------------------- /services/spring-boot/student-information-service/src/main/java/com/sliit/af/config/WebConfig.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.sliit.af.config; 5 | 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.web.servlet.config.annotation.CorsRegistry; 8 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 9 | 10 | @Configuration 11 | public class WebConfig implements WebMvcConfigurer { 12 | 13 | /** 14 | * This method will enable CORS 15 | */ 16 | @Override 17 | public void addCorsMappings(CorsRegistry registry) { 18 | registry.addMapping("/**").allowedOrigins("*").allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") 19 | .allowedHeaders("Content-Type", "Authorization", "cache-control") 20 | .exposedHeaders("Authorization", "UserID").allowCredentials(true).maxAge(3600); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /client/src/components/pages/CourseView.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import {MDBContainer} from "mdbreact" 3 | import CourseMaterialsView from "./sections/CourseMaterialsView" 4 | import AssignmentView from "./sections/AssignmentView" 5 | 6 | export default class CourseView extends React.Component { 7 | 8 | state = { 9 | cid: '' 10 | } 11 | 12 | componentDidMount() { 13 | if (this.props.match && this.props.match.params) { 14 | this.setState({cid: this.props.match.params.id}) 15 | } else { 16 | this.props.history.push('/courses/404') 17 | } 18 | } 19 | 20 | render() { 21 | return ( 22 | 23 | 24 | 25 | 26 | ) 27 | } 28 | } -------------------------------------------------------------------------------- /services/spring-boot/student-information-service/src/main/java/com/sliit/af/response/ErrorResponse.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.sliit.af.response; 5 | 6 | /** 7 | * @author vimukthi_r 8 | * @Date Apr 30, 2019 9 | * @Description 10 | * @Version 11 | */ 12 | public class ErrorResponse { 13 | private String responseCode; 14 | private String reason; 15 | 16 | /** 17 | * @return the responseCode 18 | */ 19 | public String getResponseCode() { 20 | return responseCode; 21 | } 22 | 23 | /** 24 | * @param responseCode the responseCode to set 25 | */ 26 | public void setResponseCode(String responseCode) { 27 | this.responseCode = responseCode; 28 | } 29 | 30 | /** 31 | * @return the reason 32 | */ 33 | public String getReason() { 34 | return reason; 35 | } 36 | 37 | /** 38 | * @param reason the reason to set 39 | */ 40 | public void setReason(String reason) { 41 | this.reason = reason; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /services/spring-boot/student-information-service/src/main/java/com/sliit/af/service/UserService.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.sliit.af.service; 5 | 6 | import java.util.List; 7 | 8 | import org.springframework.security.core.userdetails.UserDetailsService; 9 | 10 | import com.sliit.af.domain.UserDTO; 11 | import com.sliit.af.model.User; 12 | 13 | /** 14 | * @author Vimukthi Rajapaksha 15 | * @date Apr 15, 2019 16 | */ 17 | public interface UserService extends UserDetailsService { 18 | 19 | public User getUserById(String id); 20 | 21 | public List getByRoleName(String roleName); 22 | 23 | public List getByCourseId(String courseId); 24 | 25 | public User getByEmailAndPassword(UserDTO userDTO); 26 | 27 | public User getByEmail(String email); 28 | 29 | public User getByToken(String token); 30 | 31 | public User save(User user); 32 | 33 | public List getAll(); 34 | 35 | public void delete(String id); 36 | } 37 | -------------------------------------------------------------------------------- /services/spring-boot/student-information-service/src/main/java/com/sliit/af/model/VerificationToken.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.sliit.af.model; 5 | 6 | import java.time.LocalDateTime; 7 | 8 | import javax.validation.constraints.NotBlank; 9 | 10 | import org.springframework.data.annotation.Id; 11 | import org.springframework.data.annotation.LastModifiedDate; 12 | import org.springframework.data.mongodb.core.index.Indexed; 13 | import org.springframework.data.mongodb.core.mapping.Document; 14 | 15 | import lombok.AllArgsConstructor; 16 | import lombok.Data; 17 | import lombok.NoArgsConstructor; 18 | 19 | /** 20 | * @author vimukthi_r 21 | * 22 | */ 23 | @Document(collection = "verificationToken") 24 | @Data 25 | @NoArgsConstructor 26 | @AllArgsConstructor 27 | public class VerificationToken { 28 | @Id 29 | private String id; 30 | @Indexed 31 | @NotBlank 32 | private String token; 33 | @LastModifiedDate 34 | private LocalDateTime expiryDate; 35 | } 36 | -------------------------------------------------------------------------------- /services/spring-boot/student-information-service/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | #Server configurations 2 | server.port = 9090 3 | spring.profiles.active=dev 4 | student.info.service.url=http://localhost:9090 5 | student.info.loging.url=http://localhost:3000/ 6 | 7 | #MongoDB configuration 8 | spring.data.mongodb.host= localhost 9 | spring.data.mongodb.database= sliit-sis 10 | spring.data.mongodb.port= 27017 11 | #spring.data.mongodb.uri= mongodb://localhost/movie # Mongo database URI. When set, host and port are ignored. 12 | 13 | #Email configurations 14 | spring.mail.host=smtp.gmail.com 15 | spring.mail.port=587 16 | spring.mail.username=sl.railway.e.ticketing@gmail.com 17 | spring.mail.password=railway@123 18 | spring.mail.properties.mail.smtp.auth=true 19 | spring.mail.properties.mail.smtp.starttls.enable=true 20 | 21 | #logging 22 | logging.level.com.af2018.backend=DEBUG 23 | logging.file=output.log 24 | 25 | security.basic.enabled=false -------------------------------------------------------------------------------- /client/src/components/pages/NotFoundPage.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import {MDBCol, MDBRow} from 'mdbreact' 3 | 4 | 5 | export default class NotFoundPage extends React.Component { 6 | render() { 7 | return ( 8 | 9 |
10 | 11 | 12 |

404. That's an error.

13 |

The requested URL was not found on this server.

14 |
15 | 16 | Error 404 18 | 19 |
20 |
21 |
22 | ) 23 | } 24 | } -------------------------------------------------------------------------------- /client/src/components/pages/CourseEdit.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import {MDBContainer} from "mdbreact" 3 | import AssignmentAdd from "./sections/AssignmentAdd" 4 | import CourseMaterials from "./sections/CourseMaterials" 5 | import AssignmentEdit from "./sections/AssignmentEdit"; 6 | 7 | export default class CourseEdit extends React.Component { 8 | 9 | state = { 10 | cid: '', 11 | showErr: false, 12 | errMsg: "Required fields empty or invalid!!!" 13 | } 14 | 15 | componentDidMount() { 16 | if (this.props.match && this.props.match.params) { 17 | this.setState({cid: this.props.match.params.id}) 18 | } else { 19 | this.props.history.push('/courses/404') 20 | } 21 | } 22 | 23 | render() { 24 | return ( 25 | 26 | 27 | 28 | 29 | 30 | ) 31 | } 32 | } -------------------------------------------------------------------------------- /client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "client", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "mdbreact": "^4.16.0", 7 | "node-sass": "^4.12.0", 8 | "query-string": "^6.7.0", 9 | "react": "^16.8.6", 10 | "react-big-calendar": "^0.21.0", 11 | "react-datepicker": "^2.7.0", 12 | "react-dom": "^16.8.6", 13 | "react-dropzone": "^10.1.5", 14 | "react-router-dom": "^5.0.1", 15 | "react-scripts": "3.0.1", 16 | "react-select": "^2.4.3", 17 | "react-toastify": "^5.3.1" 18 | }, 19 | "scripts": { 20 | "start": "react-scripts start", 21 | "build": "react-scripts build", 22 | "test": "react-scripts test", 23 | "eject": "react-scripts eject" 24 | }, 25 | "eslintConfig": { 26 | "extends": "react-app" 27 | }, 28 | "browserslist": { 29 | "production": [ 30 | ">0.2%", 31 | "not dead", 32 | "not op_mini all" 33 | ], 34 | "development": [ 35 | "last 1 chrome version", 36 | "last 1 firefox version", 37 | "last 1 safari version" 38 | ] 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /client/src/components/pages/sections/FacultyList.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import {MDBListGroup, MDBListGroupItem} from "mdbreact" 3 | import {getFaculties} from '../../functions/Services' 4 | 5 | export default class FacultyList extends React.Component { 6 | 7 | state = { 8 | faculties: [] 9 | } 10 | 11 | handleClick = id => { 12 | window.location = '/faculties/' + id + '/degrees' 13 | } 14 | 15 | componentDidMount() { 16 | getFaculties() 17 | .then(res => { 18 | const faculties = [] 19 | res.faculties.map((faculty, i) => { 20 | return faculties.push( 21 | this.handleClick(faculty.fcode)}>{faculty.fname} 24 | 25 | ) 26 | }) 27 | this.setState({faculties: faculties}) 28 | }) 29 | .catch(err => { 30 | console.log(err) 31 | }) 32 | } 33 | 34 | render() { 35 | return ( 36 | 37 | {this.state.faculties} 38 | 39 | ) 40 | } 41 | } -------------------------------------------------------------------------------- /client/src/components/pages/sections/HomeBody.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import { 3 | MDBCol, 4 | MDBCard, 5 | MDBCardBody, 6 | MDBCardHeader, 7 | MDBRow, MDBIcon 8 | } from 'mdbreact'; 9 | import EventCalender from './EventCalender'; 10 | import Announcements from "./Announcements"; 11 | 12 | class HomeBody extends Component { 13 | render() { 14 | return ( 15 | 16 | 17 | 18 | Latest announcements 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | Event Calender 27 | 28 | 29 | 30 | 31 | 32 | 33 | ) 34 | } 35 | } 36 | 37 | export default HomeBody; 38 | 39 | -------------------------------------------------------------------------------- /client/build/service-worker.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Welcome to your Workbox-powered service worker! 3 | * 4 | * You'll need to register this file in your web app and you should 5 | * disable HTTP caching for this file too. 6 | * See https://goo.gl/nhQhGp 7 | * 8 | * The rest of the code is auto-generated. Please don't update this file 9 | * directly; instead, make changes to your Workbox build configuration 10 | * and re-run your build process. 11 | * See https://goo.gl/2aRDsh 12 | */ 13 | 14 | importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js"); 15 | 16 | importScripts( 17 | "/precache-manifest.4c9d33aecd1d581d3897656488e3f96a.js" 18 | ); 19 | 20 | self.addEventListener('message', (event) => { 21 | if (event.data && event.data.type === 'SKIP_WAITING') { 22 | self.skipWaiting(); 23 | } 24 | }); 25 | 26 | workbox.core.clientsClaim(); 27 | 28 | /** 29 | * The workboxSW.precacheAndRoute() method efficiently caches and responds to 30 | * requests for URLs in the manifest. 31 | * See https://goo.gl/S9QRab 32 | */ 33 | self.__precacheManifest = [].concat(self.__precacheManifest || []); 34 | workbox.precaching.precacheAndRoute(self.__precacheManifest, {}); 35 | 36 | workbox.routing.registerNavigationRoute(workbox.precaching.getCacheKeyForURL("/index.html"), { 37 | 38 | blacklist: [/^\/_/,/\/[^\/]+\.[^\/]+$/], 39 | }); 40 | -------------------------------------------------------------------------------- /client/build/asset-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": { 3 | "main.css": "/static/css/main.e9c9038f.chunk.css", 4 | "main.js": "/static/js/main.0dff254e.chunk.js", 5 | "main.js.map": "/static/js/main.0dff254e.chunk.js.map", 6 | "runtime~main.js": "/static/js/runtime~main.a8a9905a.js", 7 | "runtime~main.js.map": "/static/js/runtime~main.a8a9905a.js.map", 8 | "static/css/2.d4f8423e.chunk.css": "/static/css/2.d4f8423e.chunk.css", 9 | "static/js/2.69815b99.chunk.js": "/static/js/2.69815b99.chunk.js", 10 | "static/js/2.69815b99.chunk.js.map": "/static/js/2.69815b99.chunk.js.map", 11 | "index.html": "/index.html", 12 | "precache-manifest.4c9d33aecd1d581d3897656488e3f96a.js": "/precache-manifest.4c9d33aecd1d581d3897656488e3f96a.js", 13 | "service-worker.js": "/service-worker.js", 14 | "static/css/2.d4f8423e.chunk.css.map": "/static/css/2.d4f8423e.chunk.css.map", 15 | "static/css/main.e9c9038f.chunk.css.map": "/static/css/main.e9c9038f.chunk.css.map", 16 | "static/media/mdb.css": "/static/media/arrow_right.8ef6a08c.svg", 17 | "static/media/SLIIT-malabe.jpg": "/static/media/SLIIT-malabe.0b6863c8.jpg", 18 | "static/media/SLIIT.png": "/static/media/SLIIT.5c488492.png", 19 | "static/media/all.min.css": "/static/media/fa-solid-900.f14c3b2f.ttf", 20 | "static/media/sliit-walk.JPG": "/static/media/sliit-walk.644a5c22.JPG" 21 | } 22 | } -------------------------------------------------------------------------------- /services/spring-boot/file-manage-service/src/main/java/com/sliit/af/aspect/LoggingAspect.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.sliit.af.aspect; 5 | 6 | import org.aspectj.lang.JoinPoint; 7 | import org.aspectj.lang.annotation.After; 8 | import org.aspectj.lang.annotation.AfterReturning; 9 | import org.aspectj.lang.annotation.Aspect; 10 | import org.aspectj.lang.annotation.Before; 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | import org.springframework.context.annotation.Configuration; 14 | 15 | /** 16 | * @author Vimukthi Rajapaksha 17 | * @date Jun 2, 2019 18 | */ 19 | @Aspect 20 | @Configuration 21 | public class LoggingAspect { 22 | public static final Logger logger = LoggerFactory.getLogger(LoggingAspect.class); 23 | 24 | @Before("execution(* com.sliit.af.*.*.*(..))") 25 | public void loggingBeforeServices(JoinPoint joinPoint) { 26 | // advice 27 | logger.info("begin executing {} with parameters {}", joinPoint, joinPoint.getArgs()); 28 | } 29 | 30 | @AfterReturning(value = "execution(* com.af2018.backend.serviceImpl.*.*(..))", returning = "result") 31 | public void loggingAfterReturningServices(JoinPoint joinPoint, Object result) { 32 | // advice 33 | logger.info("{} returned with value {}", joinPoint, result); 34 | } 35 | 36 | @After(value = "execution(* com.af2018.backend.serviceImpl.*.*(..))") 37 | public void loggingAfterServices(JoinPoint joinPoint) { 38 | // advice 39 | logger.info("after execution of {}", joinPoint); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /client/src/components/pages/sections/EventCalender.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react' 2 | import BigCalendar from 'react-big-calendar' 3 | import moment from 'moment' 4 | 5 | import 'react-big-calendar/lib/sass/styles.scss' 6 | 7 | class EventCalender extends Component { 8 | 9 | state = { 10 | localizer: BigCalendar.momentLocalizer(moment), 11 | events: [ 12 | { 13 | id: 12.5, 14 | title: 'Final Exams - SEM 1', 15 | start: new Date(2019, 5, 6, 19, 30, 0), 16 | end: new Date(2019, 5, 6, 23, 30, 0), 17 | }, 18 | { 19 | id: 13, 20 | title: 'First Day - SEM 2', 21 | start: new Date(2019, 6, 1, 8, 30, 0), 22 | end: new Date(2019, 6, 1, 5, 30, 0), 23 | }, 24 | { 25 | id: 14, 26 | title: 'AF Viva', 27 | start: new Date(new Date().setHours(new Date().getHours() - 3)), 28 | end: new Date(new Date().setHours(new Date().getHours() + 3)), 29 | } 30 | ] 31 | } 32 | 33 | 34 | render() { 35 | return ( 36 | 42 | ) 43 | } 44 | } 45 | 46 | export default EventCalender; 47 | 48 | -------------------------------------------------------------------------------- /services/spring-boot/student-information-service/src/main/java/com/sliit/af/aspect/LoggingAspect.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.sliit.af.aspect; 5 | 6 | import org.aspectj.lang.JoinPoint; 7 | import org.aspectj.lang.annotation.After; 8 | import org.aspectj.lang.annotation.AfterReturning; 9 | import org.aspectj.lang.annotation.Aspect; 10 | import org.aspectj.lang.annotation.Before; 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | import org.springframework.context.annotation.Configuration; 14 | 15 | /** 16 | * @author Vimukthi Rajapaksha 17 | * @date Jun 2, 2019 18 | */ 19 | @Aspect 20 | @Configuration 21 | public class LoggingAspect { 22 | public static final Logger logger = LoggerFactory.getLogger(LoggingAspect.class); 23 | 24 | @Before("execution(* com.sliit.af.*.*.*(..))") 25 | public void loggingBeforeServices(JoinPoint joinPoint) { 26 | // advice 27 | logger.info("begin executing {} with parameters {}", joinPoint, joinPoint.getArgs()); 28 | } 29 | 30 | @AfterReturning(value = "execution(* com.af2018.backend.serviceImpl.*.*(..))", returning = "result") 31 | public void loggingAfterReturningServices(JoinPoint joinPoint, Object result) { 32 | // advice 33 | logger.info("{} returned with value {}", joinPoint, result); 34 | } 35 | 36 | @After(value = "execution(* com.af2018.backend.serviceImpl.*.*(..))") 37 | public void loggingAfterServices(JoinPoint joinPoint) { 38 | // advice 39 | logger.info("after execution of {}", joinPoint); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /client/build/static/js/runtime~main.a8a9905a.js: -------------------------------------------------------------------------------- 1 | !function(e){function r(r){for(var n,f,i=r[0],l=r[1],a=r[2],c=0,s=[];c 26 | 27 |
28 | 29 | 30 |
31 | 32 |
33 |
34 |
35 |
36 | 40 | 41 | ); 42 | } 43 | } 44 | 45 | export default App 46 | -------------------------------------------------------------------------------- /services/spring-boot/file-manage-service/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 2.1.4.RELEASE 9 | 10 | 11 | com.sliit.af 12 | file-manage-service 13 | 0.0.1-SNAPSHOT 14 | file-manage-service 15 | Demo project for Spring Boot 16 | 17 | 18 | 1.8 19 | 20 | 21 | 22 | 23 | org.springframework.boot 24 | spring-boot-starter-web 25 | 26 | 27 | 28 | org.springframework.boot 29 | spring-boot-starter-test 30 | test 31 | 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-starter-aop 36 | 37 | 38 | 39 | 40 | 41 | 42 | org.springframework.boot 43 | spring-boot-maven-plugin 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /client/src/components/pages/sections/AssignmentView.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from "react"; 2 | import {MDBCard, MDBCardHeader, MDBCol, MDBListGroup, MDBRow} from "mdbreact" 3 | import SubmitAssignment from './SubmitAssignment' 4 | import {getAssignments} from "../../functions/Services" 5 | 6 | export default class AssignmentView extends Component { 7 | 8 | state = { 9 | assignments: [] 10 | } 11 | 12 | componentDidMount() { 13 | setTimeout(() => this.readAssignments(), 400) 14 | } 15 | 16 | readAssignments = () => { 17 | getAssignments(this.props.cid) 18 | .then(async res => { 19 | var assignments = [] 20 | await res.assignments.map((item, i) => { 21 | return assignments.push( 22 | 23 | ) 24 | }) 25 | this.setState({assignments: assignments}) 26 | }) 27 | .catch(err => { 28 | console.log(err) 29 | }) 30 | } 31 | 32 | render() { 33 | return
34 | 35 | 36 | 37 | Edit Assignment / Exam 38 | 39 | {this.state.assignments} 40 | 41 | 42 | 43 | 44 |
45 | } 46 | } 47 | 48 | -------------------------------------------------------------------------------- /client/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 22 | React App 23 | 24 | 25 | 26 |
27 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /services/spring-boot/student-information-service/src/main/java/com/sliit/af/model/User.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.sliit.af.model; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | import java.util.Set; 9 | 10 | import javax.validation.Valid; 11 | import javax.validation.constraints.Email; 12 | import javax.validation.constraints.NotBlank; 13 | import javax.validation.constraints.Pattern; 14 | 15 | import org.springframework.data.annotation.Id; 16 | import org.springframework.data.mongodb.core.index.CompoundIndex; 17 | import org.springframework.data.mongodb.core.index.Indexed; 18 | import org.springframework.data.mongodb.core.mapping.DBRef; 19 | import org.springframework.data.mongodb.core.mapping.Document; 20 | 21 | import lombok.Data; 22 | import lombok.NoArgsConstructor; 23 | 24 | /** 25 | * @author vimukthi_r 26 | * 27 | */ 28 | @Document(collection = "user") 29 | @Data 30 | @NoArgsConstructor 31 | @CompoundIndex(name = "email_pwd_idx", def = "{'email' : 1, 'password' : 1}") 32 | public class User { 33 | @Id 34 | private String id; 35 | @NotBlank 36 | private String firstName; 37 | @NotBlank 38 | private String lastName; 39 | @NotBlank 40 | private String mobile; 41 | @NotBlank 42 | private String address; 43 | @NotBlank 44 | @Email 45 | @Indexed 46 | private String email; 47 | @NotBlank 48 | private String password; 49 | private int permissionLevel; 50 | private boolean isEnabled; 51 | @DBRef 52 | @Valid 53 | private Set roles; 54 | @Valid 55 | private VerificationToken verificationToken; 56 | private List faculty; 57 | private List degree; 58 | private List courses = new ArrayList<>(); 59 | @Pattern(regexp = "(^[0-9]{9}[vVxX]$)||(^[0-9]{12}$)", message="Invalid NIC") 60 | private String nic; 61 | } 62 | -------------------------------------------------------------------------------- /services/node/service.js: -------------------------------------------------------------------------------- 1 | const express = require("express") 2 | const mongoose = require("mongoose") 3 | const cors = require("cors") 4 | const jwt = require("jsonwebtoken") 5 | const facultyController = require("./controller/facultyController") 6 | const degreeController = require("./controller/degreeController") 7 | const courseController = require("./controller/courseController") 8 | 9 | 10 | mongoose.connect("mongodb://localhost:27017/siis", { useNewUrlParser: true }) 11 | const db = mongoose.connection 12 | 13 | db.on("error", (err) => { 14 | console.log("Error : " + err) 15 | }) 16 | 17 | db.once("open", () => { 18 | console.log("Connected to MongoDB") 19 | }) 20 | 21 | const app = express() 22 | 23 | app.use(express.json()) 24 | app.use(cors()) 25 | 26 | 27 | //welcome message 28 | app.get("/", (req, res) => { 29 | 30 | try { 31 | res.status(200).send("Welcome to Server on 4000") 32 | } catch (ex) { 33 | res.status(500).send("Server Error" + ex) 34 | } 35 | 36 | // jwt.verify(req.token, "c6h12o6", (err, authData) => { 37 | // if (err) { 38 | // res.status(403).json({ status: "forbidden" }) 39 | // } else { 40 | 41 | // } 42 | // }) 43 | 44 | }) 45 | 46 | 47 | //to create jwt token 48 | app.post("/login", (req, res) => { 49 | 50 | //mock user 51 | const user = { 52 | id: 100, 53 | name: "Ranmal Dewage" 54 | } 55 | 56 | jwt.sign({ user: user }, config.secret, (err, token) => { 57 | if (err) { 58 | res.status(500).json({ error: err }) 59 | } else { 60 | res.status(200).json({ token: token }) 61 | } 62 | }) 63 | 64 | }) 65 | 66 | 67 | app.use("/faculties", facultyController); 68 | app.use("/degrees", degreeController); 69 | app.use("/courses", courseController); 70 | 71 | app.listen(4000, () => { 72 | console.log("Server Running on port 4000") 73 | }) 74 | 75 | -------------------------------------------------------------------------------- /client/src/components/pages/sections/AssignmentEdit.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from "react"; 2 | import { 3 | MDBCard, 4 | MDBCardHeader, 5 | MDBCol, 6 | MDBListGroup, 7 | MDBRow 8 | } from "mdbreact" 9 | import AssignmentEditElement from "./AssignmentEditElement" 10 | 11 | import {getAssignments} from "../../functions/Services" 12 | 13 | export default class AssignmentEdit extends Component { 14 | 15 | constructor(props) { 16 | super(props) 17 | this.state = { 18 | showErr: false, 19 | errMsg: "Required fields empty or invalid", 20 | saved: false, 21 | assignments: [], 22 | ...props 23 | } 24 | } 25 | 26 | 27 | componentDidMount() { 28 | setTimeout(() => this.readAssignments(), 400) 29 | } 30 | 31 | readAssignments = () => { 32 | console.log(this.props.cid) 33 | getAssignments(this.props.cid) 34 | .then(async res => { 35 | var assignments = [] 36 | await res.assignments.map((item, i) => { 37 | return assignments.push( 38 | 39 | ) 40 | }) 41 | this.setState({assignments: assignments}) 42 | }) 43 | .catch(err => { 44 | console.log(err) 45 | }) 46 | } 47 | 48 | render() { 49 | return 50 | 51 | 52 | Edit Assignment / Exam 53 | 54 | {this.state.assignments} 55 | 56 | 57 | 58 | 59 | } 60 | } 61 | 62 | -------------------------------------------------------------------------------- /services/spring-boot/file-manage-service/src/main/java/com/sliit/af/res/UploadFileResponse.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.sliit.af.res; 5 | 6 | /** 7 | * @author vimukthi_r 8 | * 9 | */ 10 | public class UploadFileResponse { 11 | private String fileName; 12 | private String fileDownloadUri; 13 | private String fileType; 14 | private long size; 15 | 16 | /** 17 | * 18 | */ 19 | public UploadFileResponse() { 20 | super(); 21 | } 22 | 23 | /** 24 | * @param fileName 25 | * @param fileDownloadUri 26 | * @param fileType 27 | * @param size 28 | */ 29 | public UploadFileResponse(String fileName, String fileDownloadUri, String fileType, long size) { 30 | super(); 31 | this.fileName = fileName; 32 | this.fileDownloadUri = fileDownloadUri; 33 | this.fileType = fileType; 34 | this.size = size; 35 | } 36 | 37 | /** 38 | * @return the fileName 39 | */ 40 | public String getFileName() { 41 | return fileName; 42 | } 43 | 44 | /** 45 | * @param fileName the fileName to set 46 | */ 47 | public void setFileName(String fileName) { 48 | this.fileName = fileName; 49 | } 50 | 51 | /** 52 | * @return the fileDownloadUri 53 | */ 54 | public String getFileDownloadUri() { 55 | return fileDownloadUri; 56 | } 57 | 58 | /** 59 | * @param fileDownloadUri the fileDownloadUri to set 60 | */ 61 | public void setFileDownloadUri(String fileDownloadUri) { 62 | this.fileDownloadUri = fileDownloadUri; 63 | } 64 | 65 | /** 66 | * @return the fileType 67 | */ 68 | public String getFileType() { 69 | return fileType; 70 | } 71 | 72 | /** 73 | * @param fileType the fileType to set 74 | */ 75 | public void setFileType(String fileType) { 76 | this.fileType = fileType; 77 | } 78 | 79 | /** 80 | * @return the size 81 | */ 82 | public long getSize() { 83 | return size; 84 | } 85 | 86 | /** 87 | * @param size the size to set 88 | */ 89 | public void setSize(long size) { 90 | this.size = size; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /services/spring-boot/student-information-service/src/main/java/com/sliit/af/service/impl/EmailServiceImpl.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.sliit.af.service.impl; 5 | 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.beans.factory.annotation.Value; 8 | import org.springframework.mail.SimpleMailMessage; 9 | import org.springframework.mail.javamail.JavaMailSender; 10 | import org.springframework.stereotype.Service; 11 | 12 | import com.sliit.af.model.User; 13 | import com.sliit.af.service.EmailService; 14 | import com.sliit.af.util.OnRegistrationEvent; 15 | 16 | /** 17 | * @author vimukthi_r 18 | * @Date Apr 29, 2019 19 | * @Description 20 | * @Version 21 | */ 22 | @Service 23 | public class EmailServiceImpl implements EmailService { 24 | 25 | @Autowired 26 | public JavaMailSender emailSender; 27 | @Value("${spring.mail.username:ds-assignment@mail.com}") 28 | private String from; 29 | @Value("${student.info.service.url}") 30 | private String serviceUrl; 31 | 32 | /** 33 | * This method will send an email to user email with passed String subject as 34 | * email subject and String text as email body 35 | */ 36 | @Override 37 | public void sendEmail(String to, String subject, String text) { 38 | SimpleMailMessage message = new SimpleMailMessage(); 39 | message.setFrom(from); 40 | message.setTo(to); 41 | message.setSubject(subject); 42 | message.setText(text); 43 | emailSender.send(message); 44 | } 45 | 46 | @Override 47 | public void onApplicationEvent(OnRegistrationEvent event) { 48 | User user = event.getUser(); 49 | String token = user.getVerificationToken().getToken(); 50 | 51 | String recipientAddress = user.getEmail(); 52 | String subject = "Registration Confirmation"; 53 | String confirmationUrl = serviceUrl + "/users/regitrationConfirm?token=" + token; 54 | 55 | sendEmail(recipientAddress, subject, "Please Click to complete registraion : " + confirmationUrl); 56 | 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /client/build/index.html: -------------------------------------------------------------------------------- 1 | React App
-------------------------------------------------------------------------------- /client/src/components/pages/sections/CourseBreadcrumSection.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | MDBCard, 4 | MDBCardBody, 5 | MDBBreadcrumb, 6 | MDBBreadcrumbItem, 7 | MDBFormInline, 8 | } from 'mdbreact'; 9 | 10 | export default class BreadcrumSection extends React.Component { 11 | render() { 12 | return ( 13 | 14 | 15 | 16 | Degree 17 | Courses 18 | 19 | 20 | Year : 21 | 30 | Semester : 31 | 38 | 39 | 40 | 41 | ) 42 | } 43 | } 44 | 45 | -------------------------------------------------------------------------------- /client/src/components/functions/StyledDropzone.js: -------------------------------------------------------------------------------- 1 | import {useDropzone} from "react-dropzone"; 2 | import React, {useMemo} from "react"; 3 | import {MDBIcon} from "mdbreact"; 4 | 5 | export function StyledDropzone(props) { 6 | const { 7 | getRootProps, 8 | getInputProps, 9 | isDragActive, 10 | isDragAccept, 11 | isDragReject, 12 | acceptedFiles 13 | } = useDropzone(); 14 | 15 | const style = useMemo(() => ({ 16 | ...baseStyle, 17 | ...(isDragActive ? activeStyle : {}), 18 | ...(isDragAccept ? acceptStyle : {}), 19 | ...(isDragReject ? rejectStyle : {}) 20 | }), [ 21 | isDragActive, 22 | isDragReject 23 | ]); 24 | 25 | const files = acceptedFiles.map(file => ( 26 |
  • 27 | {file.path} - {file.size} bytes 28 |
  • 29 | )); 30 | 31 | return ( 32 |
    33 |
    34 | 35 |

    Drag 'n' drop some files here, or click to select files

    36 |
    37 | props.getFiles(acceptedFiles)}/> 38 | {props.saved && } 39 | 45 |
    46 | ); 47 | } 48 | 49 | const baseStyle = { 50 | flex: 1, 51 | display: 'flex', 52 | flexDirection: 'column', 53 | alignItems: 'center', 54 | padding: '20px', 55 | borderWidth: 2, 56 | borderRadius: 2, 57 | borderColor: '#eeeeee', 58 | borderStyle: 'dashed', 59 | backgroundColor: '#fafafa', 60 | color: '#bdbdbd', 61 | outline: 'none', 62 | transition: 'border .24s ease-in-out' 63 | }; 64 | 65 | const activeStyle = { 66 | borderColor: '#2196f3' 67 | }; 68 | 69 | const acceptStyle = { 70 | borderColor: '#00e676' 71 | }; 72 | 73 | const rejectStyle = { 74 | borderColor: '#ff1744' 75 | }; -------------------------------------------------------------------------------- /client/src/components/pages/sections/CourseMaterialsView.js: -------------------------------------------------------------------------------- 1 | import {Component} from "react"; 2 | import { 3 | MDBCard, 4 | MDBCardHeader, 5 | MDBCol, 6 | MDBRow, 7 | MDBListGroupItem, 8 | MDBListGroup, MDBIcon 9 | } from "mdbreact"; 10 | import React from "react" 11 | import {getCourseMaterials} from "../../functions/Services" 12 | 13 | export default class CourseMaterialsView extends Component { 14 | 15 | state = { 16 | saved: false, 17 | materials: [] 18 | } 19 | 20 | componentDidMount() { 21 | setTimeout(() => this.readMaterials(), 400) 22 | } 23 | 24 | readMaterials = () => { 25 | getCourseMaterials(this.props.cid) 26 | .then(async res => { 27 | var materials = [] 28 | await res.materials.map((item, i) => { 29 | return materials.push( 30 | 31 | 32 | 33 | 34 | {item.fileName} 35 | 36 | 37 | 38 | ) 39 | }) 40 | this.setState({materials: materials}) 41 | }) 42 | .catch(err => { 43 | console.log(err) 44 | }) 45 | } 46 | 47 | render() { 48 | return
    49 | 50 | 51 | 52 | Course Materials 53 | 54 | {this.state.materials} 55 | 56 | 57 | 58 | 59 |
    ; 60 | } 61 | } -------------------------------------------------------------------------------- /client/src/components/pages/sections/Announcements.js: -------------------------------------------------------------------------------- 1 | import {Component} from "react"; 2 | import React from "react"; 3 | import {MDBCard, MDBCardBody, MDBCardHeader, MDBCardImage} from "mdbreact"; 4 | 5 | export default class Announcements extends Component { 6 | render() { 7 | return <> 8 | 9 | Extended Campus Access Hours 10 | 11 |
      12 |
    • Campus access hours have been extended from 7.30 p.m. to 10.00 p.m. until the end of 14 | examination time 15 | period. 16 |
    • 17 |
    • Students are strictly advised to remain at the study areas and 18 | common areas during the above said time and 19 | to avoid accessing other areas of the campus premises. 20 |
    • 21 |
    • The above measure is taken in view of security of the students and 22 | staff members. 23 |
    • 24 |
    25 |
    26 |
    27 | 28 | SLIIT WALK 29 | 30 | 31 | 32 | Rotaract Club of SLIIT for receiving the award for “Club Efforts in Rotary’s Six Areas of 33 | Focus” 34 | 35 |

    Congratulations, Rotaract Club of SLIIT for receiving the award for “Club Efforts in Rotary’s Six 36 | Areas of Focus” at the Roar South Asia Awards.

    37 |
    38 |
    39 | 40 | } 41 | } -------------------------------------------------------------------------------- /client/src/components/pages/sections/MyCourses.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import {MDBListGroup, MDBListGroupItem} from "mdbreact" 3 | import {getCourse} from "../../functions/Services"; 4 | 5 | export default class MyCourses extends React.Component { 6 | 7 | state = { 8 | user: {}, 9 | courseList: [], 10 | courses: [] 11 | } 12 | 13 | componentDidMount() { 14 | var user = localStorage.getItem('sis-user') 15 | if (user) { 16 | user = JSON.parse(user) 17 | this.setState({user}) 18 | var courses = [] 19 | user.courses.map((course, i) => { 20 | return courses.push(course) 21 | }) 22 | courses.map(id => { 23 | return getCourse(id) 24 | .then(res => { 25 | this.setState({ 26 | courses: [...this.state.courses, { 27 | name: res.courses[0].cname, 28 | id: res.courses[0].ccode 29 | }] 30 | }) 31 | }) 32 | .catch(err => { 33 | console.log(err) 34 | }) 35 | }) 36 | } 37 | } 38 | 39 | handleClick = id => { 40 | var user = localStorage.getItem('sis-user') 41 | if (user) { 42 | user = JSON.parse(user) 43 | if (user.permissionLevel === 1) { 44 | window.location = '/courses/' + id + '/view' 45 | } else if (user.permissionLevel === 2) { 46 | window.location = '/courses/' + id + '/edit' 47 | } 48 | } 49 | } 50 | 51 | render() { 52 | return ( 53 | 54 | {this.state.courses.map((course, i) => { 55 | return this.handleClick(course.id)}>{course.name} 57 | }) 58 | } 59 | 60 | ) 61 | } 62 | } -------------------------------------------------------------------------------- /client/src/components/pages/DegreeList.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import {NavLink} from "react-router-dom"; 3 | import { 4 | MDBCard, 5 | MDBCardBody, 6 | MDBCardHeader, 7 | MDBCol, 8 | MDBIcon, 9 | MDBListGroup, 10 | MDBListGroupItem, MDBRow 11 | } from "mdbreact" 12 | import {getDegrees} from '../functions/Services' 13 | 14 | export default class DegreeList extends React.Component { 15 | 16 | state = { 17 | degrees: [] 18 | } 19 | 20 | componentDidMount() { 21 | 22 | if (this.props.match && this.props.match.params) { 23 | const did = this.props.match.params.id 24 | getDegrees(did) 25 | .then(res => { 26 | const degrees = [] 27 | res.degrees.map((degree, i) => { 28 | const to = "/degree/" + degree.dcode + "/courses" 29 | return degrees.push( 30 | 31 | 32 | 33 | {degree.dname} 34 | 35 | 36 | ) 37 | }) 38 | this.setState({degrees: degrees}) 39 | }) 40 | .catch(err => { 41 | console.log(err) 42 | }) 43 | } else { 44 | this.props.history.push('/faculties/404') 45 | } 46 | } 47 | 48 | render() { 49 | return ( 50 | 51 | 52 | 53 | Degrees 54 | 55 | 56 | {this.state.degrees} 57 | 58 | 59 | 60 | 61 | 62 | ) 63 | } 64 | } -------------------------------------------------------------------------------- /services/spring-boot/student-information-service/src/main/java/com/sliit/af/util/ExceptionHandlerController.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.sliit.af.util; 5 | 6 | import static java.util.stream.Collectors.toMap; 7 | 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | import java.util.Objects; 11 | 12 | import org.springframework.http.HttpStatus; 13 | import org.springframework.validation.FieldError; 14 | import org.springframework.web.bind.MethodArgumentNotValidException; 15 | import org.springframework.web.bind.annotation.ExceptionHandler; 16 | import org.springframework.web.bind.annotation.ResponseBody; 17 | import org.springframework.web.bind.annotation.ResponseStatus; 18 | import org.springframework.web.bind.annotation.RestControllerAdvice; 19 | 20 | import com.sliit.af.response.ErrorResponse; 21 | 22 | /** 23 | * @author vimukthi_r 24 | * @Date Apr 30, 2019 25 | * @Description 26 | * @Version 27 | */ 28 | @RestControllerAdvice 29 | public class ExceptionHandlerController { 30 | 31 | /** 32 | * This method will handle globally thrown MethodArgumentNotValid Exceptions And 33 | * will return an errorResponse 34 | */ 35 | @ExceptionHandler(MethodArgumentNotValidException.class) 36 | @ResponseBody 37 | @ResponseStatus(HttpStatus.BAD_REQUEST) 38 | public ErrorResponse handleMethodArgumentNotValid(MethodArgumentNotValidException ex) { 39 | 40 | Map errorFieldList = new HashMap<>(); 41 | Map nullFieldList = null; 42 | ErrorResponse errorResponse = new ErrorResponse(); 43 | 44 | errorResponse.setResponseCode("01"); 45 | try { 46 | 47 | // getting format invalid errorList 48 | errorFieldList = ex.getBindingResult().getFieldErrors().stream() 49 | .filter(i -> Objects.nonNull(i.getRejectedValue())) 50 | .collect(toMap(FieldError::getField, FieldError::getDefaultMessage)); 51 | 52 | // getting null errorList 53 | nullFieldList = ex.getBindingResult().getFieldErrors().stream() 54 | .filter(i -> Objects.isNull(i.getRejectedValue())) 55 | .collect(toMap(FieldError::getField, FieldError::getDefaultMessage)); 56 | 57 | if (!nullFieldList.isEmpty()) { 58 | errorResponse.setReason(nullFieldList.toString()); 59 | } else { 60 | errorResponse.setReason(errorFieldList.toString()); 61 | } 62 | 63 | } catch (Exception e) { 64 | errorResponse.setReason(e.getMessage()); 65 | } 66 | return errorResponse; 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /services/spring-boot/af-zuulservice/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | net.epiclanka.acs 7 | acs-zuulservice 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | acs-zuulservice 12 | zuul for ACS 3DS2 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.0.4.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 1.8 25 | Finchley.SR1 26 | 27 | 28 | 29 | 30 | org.springframework.cloud 31 | spring-cloud-starter-netflix-eureka-client 32 | 33 | 34 | org.springframework.cloud 35 | spring-cloud-starter-netflix-zuul 36 | 37 | 38 | org.springframework.cloud 39 | spring-cloud-starter-openfeign 40 | 41 | 42 | 43 | org.springframework.boot 44 | spring-boot-starter-test 45 | test 46 | 47 | 48 | 49 | 50 | 51 | 52 | org.springframework.cloud 53 | spring-cloud-dependencies 54 | ${spring-cloud.version} 55 | pom 56 | import 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | org.springframework.boot 65 | spring-boot-maven-plugin 66 | 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /services/spring-boot/student-information-service/src/test/java/com/sliit/af/studentinformationservice/controller/UserControllerTests.java: -------------------------------------------------------------------------------- 1 | package com.sliit.af.studentinformationservice.controller; 2 | 3 | import static org.hamcrest.CoreMatchers.is; 4 | import static org.hamcrest.Matchers.hasSize; 5 | import static org.mockito.BDDMockito.given; 6 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; 7 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; 8 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 9 | 10 | import java.util.Arrays; 11 | import java.util.List; 12 | 13 | import org.junit.Test; 14 | import org.junit.runner.RunWith; 15 | import org.springframework.beans.factory.annotation.Autowired; 16 | import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; 17 | import org.springframework.boot.test.context.TestConfiguration; 18 | import org.springframework.boot.test.mock.mockito.MockBean; 19 | import org.springframework.context.annotation.Bean; 20 | import org.springframework.http.MediaType; 21 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 22 | import org.springframework.test.context.junit4.SpringRunner; 23 | import org.springframework.test.web.servlet.MockMvc; 24 | 25 | import com.sliit.af.controller.UserController; 26 | import com.sliit.af.model.User; 27 | import com.sliit.af.service.UserService; 28 | 29 | @RunWith(SpringRunner.class) 30 | @WebMvcTest(UserController.class) 31 | public class UserControllerTests { 32 | 33 | @TestConfiguration 34 | public static class UserControllerTestConfiguration { 35 | 36 | @Bean 37 | public BCryptPasswordEncoder bCryptPasswordEncoder() { 38 | return new BCryptPasswordEncoder(); 39 | } 40 | } 41 | 42 | @Autowired 43 | private MockMvc mockMvc; 44 | 45 | @MockBean 46 | private UserService userService; 47 | 48 | @Test 49 | // @WithMockUser(username="admin",roles={"USER","ADMIN"}) 50 | public void getUsersTest() throws Exception { 51 | User user = new User(); 52 | user.setFirstName("admin"); 53 | 54 | List allUsers = Arrays.asList(user); 55 | 56 | given(userService.getAll()).willReturn(allUsers); 57 | 58 | mockMvc.perform(post("/users").contentType(MediaType.APPLICATION_JSON_VALUE)).andExpect(status().isOk()) 59 | .andExpect(jsonPath("$", hasSize(1))).andExpect(jsonPath("$[0].username", is(user.getFirstName()))); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /services/spring-boot/student-information-service/src/main/java/com/sliit/af/config/JWTAuthorizationFilter.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.sliit.af.config; 5 | 6 | import static com.sliit.af.util.Param.HEADER_STRING; 7 | import static com.sliit.af.util.Param.SECRET; 8 | import static com.sliit.af.util.Param.TOKEN_PREFIX; 9 | 10 | import java.io.IOException; 11 | import java.util.ArrayList; 12 | 13 | import javax.servlet.FilterChain; 14 | import javax.servlet.ServletException; 15 | import javax.servlet.http.HttpServletRequest; 16 | import javax.servlet.http.HttpServletResponse; 17 | 18 | import org.springframework.security.authentication.AuthenticationManager; 19 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 20 | import org.springframework.security.core.context.SecurityContextHolder; 21 | import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; 22 | 23 | import com.auth0.jwt.JWT; 24 | import com.auth0.jwt.algorithms.Algorithm; 25 | 26 | /** 27 | * This class will authorize users 28 | * 29 | */ 30 | public class JWTAuthorizationFilter extends BasicAuthenticationFilter { 31 | 32 | public JWTAuthorizationFilter(AuthenticationManager authManager) { 33 | super(authManager); 34 | } 35 | 36 | /** 37 | * This method will check is req contains an authorization header 38 | */ 39 | @Override 40 | protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain) 41 | throws IOException, ServletException { 42 | 43 | String header = req.getHeader(HEADER_STRING); 44 | 45 | if (header == null || !header.startsWith(TOKEN_PREFIX)) { 46 | chain.doFilter(req, res); 47 | return; 48 | } 49 | 50 | UsernamePasswordAuthenticationToken authentication = getAuthentication(req); 51 | 52 | SecurityContextHolder.getContext().setAuthentication(authentication); 53 | chain.doFilter(req, res); 54 | 55 | } 56 | 57 | /** 58 | * This method will verify token using secret key 59 | */ 60 | private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) { 61 | String token = request.getHeader(HEADER_STRING); 62 | if (token != null) { 63 | // parse the token. 64 | String user = JWT.require(Algorithm.HMAC512(SECRET.getBytes())).build() 65 | .verify(token.replace(TOKEN_PREFIX, "")).getSubject(); 66 | 67 | if (user != null) { 68 | return new UsernamePasswordAuthenticationToken(user, null, new ArrayList<>()); 69 | } 70 | return null; 71 | } 72 | return null; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /services/spring-boot/af-eurekaserver/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | net.epiclanka.acs 8 | acs-eurekaserver 9 | 0.0.1-SNAPSHOT 10 | jar 11 | 12 | acs-eurekaserver 13 | eureka server for ACS 3DS2 14 | 15 | 16 | org.springframework.boot 17 | spring-boot-starter-parent 18 | 2.0.4.RELEASE 19 | 20 | 21 | 22 | 23 | 24 | 25 | org.springframework.cloud 26 | spring-cloud-dependencies 27 | Finchley.SR1 28 | pom 29 | import 30 | 31 | 32 | 33 | 34 | 35 | UTF-8 36 | UTF-8 37 | 1.8 38 | Dalston.SR1 39 | 40 | 41 | 42 | 43 | 44 | org.springframework.boot 45 | spring-boot-starter-actuator 46 | 47 | 48 | 49 | org.springframework.cloud 50 | spring-cloud-starter-config 51 | 52 | 53 | 54 | org.springframework.boot 55 | spring-boot-starter 56 | 57 | 58 | 59 | org.springframework.cloud 60 | spring-cloud-starter-netflix-eureka-server 61 | 62 | 63 | 64 | org.springframework.boot 65 | spring-boot-starter-test 66 | test 67 | 68 | 69 | 70 | 71 | 72 | 73 | org.springframework.boot 74 | spring-boot-maven-plugin 75 | 76 | 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /client/src/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /client/src/components/pages/sections/AssignmentEditElement.js: -------------------------------------------------------------------------------- 1 | import {Component} from "react"; 2 | import {MDBBtn, MDBCol, MDBInput, MDBListGroupItem, MDBRow} from "mdbreact"; 3 | import DatePicker from "react-datepicker"; 4 | import React from "react"; 5 | import {updateAssignments} from "../../functions/Services" 6 | import {toast} from "react-toastify" 7 | import moment from 'moment' 8 | 9 | export default class AssignmentEditElement extends Component { 10 | 11 | state = {...this.props.item} 12 | 13 | componentDidMount() { 14 | // setTimeout(() => this.setState({...this.props.item}), 400) 15 | } 16 | 17 | handleDateChange = dt => { 18 | const date = moment(dt).format('YYYY-MM-DD') 19 | this.setState({dueDate: date}) 20 | } 21 | 22 | handleUpdate = id => { 23 | if (this.state.dueDate && this.state.dueDate !== this.props.item.dueDate) { 24 | updateAssignments(this.props.cid, id, {dueDate: this.state.dueDate}) 25 | .then(res => { 26 | toast.success("Assignment updated") 27 | }) 28 | .catch(err => { 29 | console.log(err) 30 | toast.error("Server error") 31 | }) 32 | } else { 33 | toast.error("Nothing to change") 34 | } 35 | } 36 | 37 | render() { 38 | return 39 | 40 | 41 | 50 | 51 | 52 |
    53 | 61 |
    62 |
    63 | 64 | 65 | this.handleUpdate(this.props.item._id)}>Update 67 | 68 | 69 |
    ; 70 | } 71 | } -------------------------------------------------------------------------------- /services/spring-boot/student-information-service/src/main/java/com/sliit/af/config/WebSecurity.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.sliit.af.config; 5 | 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.http.HttpMethod; 9 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 10 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 11 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 12 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 13 | import org.springframework.security.config.http.SessionCreationPolicy; 14 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 15 | 16 | import com.sliit.af.service.UserService; 17 | 18 | /** 19 | * @author Vimukthi Rajapaksha 20 | * @date Apr 28, 2019 21 | */ 22 | @Configuration 23 | @EnableWebSecurity 24 | public class WebSecurity extends WebSecurityConfigurerAdapter { 25 | private final UserService userService; 26 | private final BCryptPasswordEncoder bCryptPasswordEncoder; 27 | 28 | @Autowired 29 | public WebSecurity(UserService usersService, BCryptPasswordEncoder bCryptPasswordEncoder) { 30 | this.userService = usersService; 31 | this.bCryptPasswordEncoder = bCryptPasswordEncoder; 32 | } 33 | 34 | /** 35 | * This method will, 1. permit all requests for /login end point 2. permit POST 36 | * requests for /users/register end point 3. permit all GET requests 37 | * 38 | * Other requests need to be authorized 39 | */ 40 | @Override 41 | protected void configure(HttpSecurity http) throws Exception { 42 | 43 | http.cors(); 44 | 45 | // permit all requests for login end point 46 | http.csrf().disable().authorizeRequests().antMatchers(HttpMethod.OPTIONS, "/login").permitAll() 47 | .antMatchers(HttpMethod.GET, "/swagger-ui.html").permitAll() 48 | .antMatchers(HttpMethod.GET, "/users/regitrationConfirm").permitAll() 49 | // POST requests for /users end point authentication needed for instructors 50 | .antMatchers(HttpMethod.POST, "/users").permitAll() 51 | // .access("not( hasRole('" + Param.INSTRUCTOR + "') ) and isAuthenticated()") 52 | // permit POST requests for /users end point 53 | .anyRequest().authenticated().and().addFilter(new JWTAuthenticationFilter(authenticationManager())) 54 | .addFilter(new JWTAuthorizationFilter(authenticationManager())) 55 | // this disables session creation on Spring Security 56 | .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); 57 | } 58 | 59 | /** 60 | * This method is configuring auth object 61 | */ 62 | @Override 63 | protected void configure(AuthenticationManagerBuilder auth) throws Exception { 64 | auth.userDetailsService(userService).passwordEncoder(bCryptPasswordEncoder); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /services/spring-boot/student-information-service/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | org.springframework.boot 8 | spring-boot-starter-parent 9 | 2.1.4.RELEASE 10 | 11 | 12 | com.sliit.af 13 | student-information-service 14 | 0.0.1-SNAPSHOT 15 | student-information-service 16 | Demo project for Spring Boot 17 | 18 | 19 | 1.8 20 | 21 | 22 | 23 | 24 | org.springframework.boot 25 | spring-boot-starter-aop 26 | 27 | 28 | org.springframework.boot 29 | spring-boot-starter-data-mongodb 30 | 31 | 32 | org.springframework.boot 33 | spring-boot-starter-web 34 | 35 | 36 | 37 | org.springframework.boot 38 | spring-boot-starter-test 39 | test 40 | 41 | 42 | org.projectlombok 43 | lombok 44 | provided 45 | 46 | 47 | 48 | org.springframework.boot 49 | spring-boot-starter-mail 50 | 51 | 52 | 53 | io.springfox 54 | springfox-swagger2 55 | 2.9.2 56 | 57 | 58 | 59 | io.springfox 60 | springfox-swagger-ui 61 | 2.9.2 62 | 63 | 64 | 65 | org.springframework.boot 66 | spring-boot-starter-security 67 | 68 | 69 | 71 | 72 | 73 | com.auth0 74 | java-jwt 75 | 3.8.0 76 | 77 | 78 | com.google.code.gson 79 | gson 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | org.springframework.boot 88 | spring-boot-maven-plugin 89 | 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /client/README.md: -------------------------------------------------------------------------------- 1 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 2 | 3 | ## Available Scripts 4 | 5 | In the project directory, you can run: 6 | 7 | ### `npm start` 8 | 9 | Runs the app in the development mode.
    10 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser. 11 | 12 | The page will reload if you make edits.
    13 | You will also see any lint errors in the console. 14 | 15 | ### `npm test` 16 | 17 | Launches the test runner in the interactive watch mode.
    18 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 19 | 20 | ### `npm run build` 21 | 22 | Builds the app for production to the `build` folder.
    23 | It correctly bundles React in production mode and optimizes the build for the best performance. 24 | 25 | The build is minified and the filenames include the hashes.
    26 | Your app is ready to be deployed! 27 | 28 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 29 | 30 | ### `npm run eject` 31 | 32 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!** 33 | 34 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. 35 | 36 | Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. 37 | 38 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. 39 | 40 | ## Learn More 41 | 42 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 43 | 44 | To learn React, check out the [React documentation](https://reactjs.org/). 45 | 46 | ### Code Splitting 47 | 48 | This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting 49 | 50 | ### Analyzing the Bundle Size 51 | 52 | This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size 53 | 54 | ### Making a Progressive Web App 55 | 56 | This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app 57 | 58 | ### Advanced Configuration 59 | 60 | This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration 61 | 62 | ### Deployment 63 | 64 | This section has moved here: https://facebook.github.io/create-react-app/docs/deployment 65 | 66 | ### `npm run build` fails to minify 67 | 68 | This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify 69 | -------------------------------------------------------------------------------- /client/src/components/pages/SearchCourse.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import qs from 'query-string' 3 | import { 4 | MDBCard, 5 | MDBCardBody, 6 | MDBCardHeader, 7 | MDBCol, 8 | MDBCollapse, 9 | MDBListGroup, 10 | MDBListGroupItem, 11 | MDBRow 12 | } from "mdbreact" 13 | import {searchCourse} from '../functions/Services' 14 | import CourseElement from "./sections/CourseElement"; 15 | 16 | export default class SearchCourse extends React.Component { 17 | 18 | state = { 19 | name: '', 20 | collapseID: '', 21 | courses: [] 22 | } 23 | 24 | toggleCollapse = collapseID => () => { 25 | this.setState(prevState => ({ 26 | collapseID: prevState.collapseID !== collapseID ? collapseID : "" 27 | })); 28 | } 29 | 30 | componentDidMount() { 31 | const name = qs.parse(this.props.location.search).name 32 | if (name) { 33 | this.setState({name}, () => this.loadCourses()) 34 | } 35 | } 36 | 37 | loadCourses = () => { 38 | searchCourse(this.state.name) 39 | .then(res => { 40 | this.setState({courses: res.courses}) 41 | }) 42 | .catch(err => { 43 | console.log(err) 44 | }) 45 | } 46 | 47 | render() { 48 | return ( 49 | 50 | 51 | 52 | Search results for course : {this.state.name} 53 | 54 | 55 | {this.state.courses.map((course, i) => { 56 | return ( 57 | 58 | 59 |
    {course.cname} 61 |
    63 |
    64 |
    65 | 66 | 67 | 68 |
    69 |
    70 | ) 71 | })} 72 |
    73 |
    74 |
    75 |
    76 |
    77 | ) 78 | } 79 | } -------------------------------------------------------------------------------- /services/spring-boot/file-manage-service/src/main/java/com/sliit/af/service/impl/FileServiceImpl.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.sliit.af.service.impl; 5 | 6 | import java.io.IOException; 7 | import java.net.MalformedURLException; 8 | import java.nio.file.Files; 9 | import java.nio.file.Path; 10 | import java.nio.file.Paths; 11 | import java.nio.file.StandardCopyOption; 12 | import java.util.Objects; 13 | 14 | import org.springframework.beans.factory.annotation.Value; 15 | import org.springframework.core.io.Resource; 16 | import org.springframework.core.io.UrlResource; 17 | import org.springframework.stereotype.Service; 18 | import org.springframework.util.StringUtils; 19 | import org.springframework.web.multipart.MultipartFile; 20 | 21 | import com.sliit.af.exception.FileStorageException; 22 | import com.sliit.af.exception.MyFileNotFoundException; 23 | import com.sliit.af.service.FileService; 24 | 25 | /** 26 | * @author vimukthi_r 27 | * 28 | */ 29 | @Service 30 | public class FileServiceImpl implements FileService { 31 | 32 | @Value("${file.upload-dir:./uploads}") 33 | private String uploadDir; 34 | private Path fileStorageLocation = null; 35 | 36 | public void generateFileStorageLocation(String uploadDir) { 37 | try { 38 | this.fileStorageLocation = Paths.get(uploadDir).toAbsolutePath().normalize(); 39 | Files.createDirectories(this.fileStorageLocation); 40 | } catch (Exception e) { 41 | throw new FileStorageException("Could not create the directory where the uploaded files will be stored."); 42 | } 43 | } 44 | 45 | @Override 46 | public String storeFile(MultipartFile file) { 47 | // Normalize file name 48 | String fileName = StringUtils.cleanPath(file.getOriginalFilename()); 49 | 50 | try { 51 | if(Objects.isNull(fileStorageLocation)) { 52 | generateFileStorageLocation(this.uploadDir); 53 | } 54 | // Check if the file's name contains invalid characters 55 | if (fileName.contains("..")) { 56 | throw new FileStorageException("Sorry! Filename contains invalid path sequence " + fileName); 57 | } 58 | 59 | // Copy file to the target location (Replacing existing file with the same name) 60 | Path targetLocation = this.fileStorageLocation.resolve(fileName); 61 | Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING); 62 | 63 | return fileName; 64 | } catch (IOException ex) { 65 | throw new FileStorageException("Could not store file " + fileName + ". Please try again!"); 66 | } 67 | } 68 | 69 | @Override 70 | public Resource loadFileAsResource(String fileName) { 71 | try { 72 | if(Objects.isNull(fileStorageLocation)) { 73 | generateFileStorageLocation(this.uploadDir); 74 | } 75 | Path filePath = this.fileStorageLocation.resolve(fileName).normalize(); 76 | Resource resource = new UrlResource(filePath.toUri()); 77 | if (resource.exists()) { 78 | return resource; 79 | } else { 80 | throw new MyFileNotFoundException("File not found " + fileName); 81 | } 82 | } catch (MalformedURLException ex) { 83 | throw new MyFileNotFoundException("File not found " + fileName); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /client/src/components/Routes.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import {Route, Switch} from 'react-router-dom' 3 | import Home from './pages/Home' 4 | import Profile from './pages/Profile' 5 | import About from './pages/About' 6 | import Contact from './pages/Contact' 7 | import Register from './pages/Register' 8 | import SearchCourse from './pages/SearchCourse' 9 | import CourseView from './pages/CourseView' 10 | import CourseEdit from './pages/CourseEdit' 11 | import DegreeList from './pages/DegreeList' 12 | import CourseList from './pages/CourseList' 13 | import NotFoundPage from './pages/NotFoundPage' 14 | import FacultyManagement from './admin/FacultyManagement' 15 | import InstructorManagement from './admin/InstructorManagement' 16 | import CourseManagement from './admin/CourseManagement' 17 | import AdminManagement from './admin/AdminManagement' 18 | 19 | class Routes extends React.Component { 20 | render() { 21 | var user = localStorage.getItem('sis-user') 22 | if (user) { 23 | user = JSON.parse(user) 24 | } 25 | return ( 26 | 27 | {/*any user*/} 28 | 29 | 30 | 31 | 32 | 33 | 34 | {/*admin*/} 35 | {user && user.permissionLevel === 3 && 36 | } 37 | {user && user.permissionLevel === 3 && 38 | } 39 | {user && user.permissionLevel === 3 && 40 | } 41 | {user && user.permissionLevel === 3 && 42 | } 43 | {user && user.permissionLevel === 3 && 44 | } 45 | 46 | {/*instructor, admin*/} 47 | {user && (user.permissionLevel === 1 || user.permissionLevel === 3) && 48 | } 49 | 50 | {/*instructor , student, admin*/} 51 | {user && 1 <= user.permissionLevel <= 3 && 52 | } 53 | {user && 1 <= user.permissionLevel <= 3 && 54 | } 55 | {user && 1 <= user.permissionLevel <= 3 && 56 | } 57 | {user && 1 <= user.permissionLevel <= 3 && 58 | } 59 | {user && 1 <= user.permissionLevel <= 3 && 60 | } 61 | 62 | 63 | 64 | ); 65 | } 66 | } 67 | 68 | export default Routes; -------------------------------------------------------------------------------- /client/src/components/pages/sections/CourseElement.js: -------------------------------------------------------------------------------- 1 | import {MDBCol, MDBCard, MDBCardBody, MDBCardText, MDBBtn, MDBInput, MDBFormInline} from "mdbreact" 2 | import React, {Component} from "react" 3 | import {updateUser} from '../../functions/Services' 4 | import {toast} from "react-toastify" 5 | 6 | export default class CourseElement extends Component { 7 | 8 | state = { 9 | ek: '', 10 | user: {} 11 | } 12 | 13 | handleChange = event => { 14 | let value = event; 15 | if (event.target) { 16 | value = event.target.value; 17 | } 18 | this.setState({[event.target.name]: value}) 19 | } 20 | 21 | componentDidMount() { 22 | var user = localStorage.getItem('sis-user') 23 | if (user) { 24 | user = JSON.parse(user) 25 | this.setState({user}) 26 | } 27 | } 28 | 29 | handleSubmit = event => { 30 | if (this.state.user && this.state.user.permissionLevel === 1) { 31 | if (this.state.ek === this.props.course.ccode) { 32 | const body = { 33 | id: this.state.user.id, 34 | courses: this.state.user.courses ? [...this.state.user.courses, this.props.course.ccode] : [this.props.course.ccode] 35 | } 36 | updateUser(body) 37 | .then(res => { 38 | const data = {...this.state.user, courses: body.courses} 39 | localStorage.setItem('sis-user', JSON.stringify(data)) 40 | window.location = "/courses/" + this.props.course.ccode + "/view" 41 | }) 42 | .catch(err => { 43 | console.log(err) 44 | }) 45 | } else { 46 | toast.error("Invalid enrollment key!!!") 47 | } 48 | } else { 49 | toast.error("Only students can enroll to this course!!!") 50 | } 51 | event.preventDefault() 52 | event.stopPropagation() 53 | } 54 | 55 | render() { 56 | const link = "/courses/" + this.props.course.ccode + "/view" 57 | return ( 58 | 59 | 60 | 61 | 62 | {this.props.course.description} 63 | 64 | {this.state.user && this.state.user.courses && this.state.user.courses.includes(this.props.course.ccode) ? 65 |

    window.location = link} className="text-primary">You have already enrolled 66 | to 67 | this course

    68 | : 69 | 70 | 79 | Enroll 80 | 81 | } 82 |
    83 |
    84 |
    85 | ) 86 | } 87 | } -------------------------------------------------------------------------------- /client/build/static/css/main.e9c9038f.chunk.css: -------------------------------------------------------------------------------- 1 | .about-top-diagonal{position:relative;width:100%;height:50px;overflow:hidden}.about-top-diagonal:before{-webkit-transform:skewY(5deg);transform:skewY(5deg);-webkit-transform-origin:bottom right;transform-origin:bottom right}.about-top-diagonal:after,.about-top-diagonal:before{content:"";position:absolute;top:0;width:50%;height:100%;background-color:#2196f3;background-size:200%,0}.about-top-diagonal:after{left:50%;background-position:-100% 0;-webkit-transform:skewY(-5deg);transform:skewY(-5deg);-webkit-transform-origin:bottom left;transform-origin:bottom left}.top-diagonal{position:relative;width:100%;height:50px;overflow:hidden}.top-diagonal:before{-webkit-transform:skewY(5deg);transform:skewY(5deg);-webkit-transform-origin:bottom right;transform-origin:bottom right}.top-diagonal:after,.top-diagonal:before{content:"";position:absolute;top:0;width:50%;height:100%;background-color:#2bbbad;background-size:200%,0}.top-diagonal:after{left:50%;background-position:-100% 0;-webkit-transform:skewY(-5deg);transform:skewY(-5deg);-webkit-transform-origin:bottom left;transform-origin:bottom left}::-webkit-scrollbar{display:none}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#ededee}a{color:inherit}.list-group-flush{color:#495057}.active{background-color:#e9ecef}main{background-color:#ededee}.navbar-brand{margin-left:15px;color:#2196f3!important}.sidebar-fixed{left:0;top:0;height:100vh;width:270px;box-shadow:0 2px 5px 0 rgba(0,0,0,.16),0 2px 10px 0 rgba(0,0,0,.12);z-index:1050;background-color:#fff;padding:0 1.5rem 1.5rem}.flexible-navbar{-webkit-transition:padding-left .5s;transition:padding-left .5s;padding-left:270px;background:#fff}#content{margin-left:270px}.sidebar-fixed .logo-wrapper img{width:100%;padding:2.5rem}.list-group-item{display:block!important;-webkit-transition:background-color .3s;transition:background-color .3s}.list-group-item:hover{color:#49505b;text-decoration:none;background-color:#f8f9fa}.list-group .active{box-shadow:0 2px 5px 0 rgba(0,0,0,.16),0 2px 10px 0 rgba(0,0,0,.12);border-radius:5px}.card-title{font-size:1.5rem;font-weight:600}.card-subtitle{font-size:1.25rem;font-weight:600}.full{height:70vh}.bad-gateway-row{margin:0;position:absolute;top:50%;left:55%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.card .view.gradient-card-header{padding:1rem;text-align:center}.card.card-cascade h4,.card h3{margin-bottom:0}.cascading-admin-card .admin-up{margin-left:4%;margin-right:4%;margin-top:-20px}.cascading-admin-card .admin-up .fa{box-shadow:0 2px 9px 0 rgba(0,0,0,.2),0 2px 13px 0 rgba(0,0,0,.19);padding:1.7rem;font-size:2rem;color:#fff;text-align:left;margin-right:1rem;border-radius:3px}.cascading-admin-card .admin-up .data{float:right;margin-top:2rem;text-align:right}.admin-up .data p{color:#999;font-size:12px}.classic-admin-card .card-body{color:#fff;margin-bottom:0;padding:.9rem}.classic-admin-card .card-body p{font-size:13px;opacity:.7;margin-bottom:0}.classic-admin-card .card-body h4{margin-top:10px}.form-inline{flex-flow:unset}.breadcrumb{margin:0}.activeClass .list-group-item{z-index:5;color:#fff;border-color:#007bff;box-shadow:0 2px 5px 0 rgba(0,0,0,.16),0 2px 10px 0 rgba(0,0,0,.12);border-radius:5px!important;background-color:#007bff!important}.page-footer{margin-left:270px}@media (max-width:1199.98px){.sidebar-fixed{display:none}.flexible-content{padding-left:0}.flexible-navbar{padding-left:10px}#content,.page-footer{margin-left:0}.card.cascading-admin-card{margin-top:2.5rem}}@media (max-width:576px){.card.cascading-admin-card{margin-top:2.5rem}#breadcrumb{flex-direction:column}} 2 | /*# sourceMappingURL=main.e9c9038f.chunk.css.map */ -------------------------------------------------------------------------------- /services/spring-boot/student-information-service/src/main/java/com/sliit/af/config/JWTAuthenticationFilter.java: -------------------------------------------------------------------------------- 1 | package com.sliit.af.config; 2 | 3 | import static com.auth0.jwt.algorithms.Algorithm.HMAC512; 4 | import static com.sliit.af.util.Param.EXPIRATION_TIME; 5 | import static com.sliit.af.util.Param.HEADER_STRING; 6 | import static com.sliit.af.util.Param.SECRET; 7 | import static com.sliit.af.util.Param.TOKEN_PREFIX; 8 | 9 | import java.io.IOException; 10 | import java.io.PrintWriter; 11 | import java.util.ArrayList; 12 | import java.util.Date; 13 | import java.util.Objects; 14 | 15 | import javax.servlet.FilterChain; 16 | import javax.servlet.ServletContext; 17 | import javax.servlet.ServletException; 18 | import javax.servlet.http.HttpServletRequest; 19 | import javax.servlet.http.HttpServletResponse; 20 | 21 | import org.springframework.security.authentication.AuthenticationManager; 22 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 23 | import org.springframework.security.core.Authentication; 24 | import org.springframework.security.core.AuthenticationException; 25 | import org.springframework.security.core.userdetails.User; 26 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; 27 | import org.springframework.web.context.WebApplicationContext; 28 | import org.springframework.web.context.support.WebApplicationContextUtils; 29 | 30 | import com.auth0.jwt.JWT; 31 | import com.fasterxml.jackson.databind.ObjectMapper; 32 | import com.google.gson.Gson; 33 | import com.google.gson.GsonBuilder; 34 | import com.sliit.af.domain.UserDTO; 35 | import com.sliit.af.service.UserService; 36 | 37 | /** 38 | * This class will do user authentication 39 | * 40 | */ 41 | public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter { 42 | 43 | private AuthenticationManager authenticationManager; 44 | private UserService userService; 45 | 46 | public JWTAuthenticationFilter(AuthenticationManager authenticationManager) { 47 | this.authenticationManager = authenticationManager; 48 | } 49 | 50 | /** 51 | * This method will authenticate the user using email and password 52 | */ 53 | @Override 54 | public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res) 55 | throws AuthenticationException { 56 | try { 57 | UserDTO creds = new ObjectMapper().readValue(req.getInputStream(), UserDTO.class); 58 | 59 | return authenticationManager.authenticate( 60 | new UsernamePasswordAuthenticationToken(creds.getEmail(), creds.getPassword(), new ArrayList<>())); 61 | } catch (IOException e) { 62 | throw new RuntimeException(e); 63 | } 64 | } 65 | 66 | /** 67 | * This method will add auth token to header after successful login 68 | */ 69 | @Override 70 | protected void successfulAuthentication(HttpServletRequest req, HttpServletResponse res, FilterChain chain, 71 | Authentication auth) throws IOException, ServletException { 72 | Gson gson = new GsonBuilder().setPrettyPrinting().create(); 73 | if (Objects.isNull(userService)) { 74 | ServletContext servletContext = req.getServletContext(); 75 | WebApplicationContext webApplicationContext = WebApplicationContextUtils 76 | .getWebApplicationContext(servletContext); 77 | userService = webApplicationContext.getBean(UserService.class); 78 | } 79 | 80 | PrintWriter out = res.getWriter(); 81 | String userEmail = ((User) auth.getPrincipal()).getUsername(); 82 | 83 | String token = JWT.create().withSubject(((User) auth.getPrincipal()).getUsername()) 84 | .withExpiresAt(new Date(System.currentTimeMillis() + EXPIRATION_TIME)).sign(HMAC512(SECRET.getBytes())); 85 | res.addHeader(HEADER_STRING, TOKEN_PREFIX + token); 86 | 87 | out.print(gson.toJson(userService.getByEmail(userEmail))); 88 | out.flush(); 89 | } 90 | } -------------------------------------------------------------------------------- /services/spring-boot/file-manage-service/src/main/java/com/sliit/af/controller/FileController.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.sliit.af.controller; 5 | 6 | import java.io.IOException; 7 | import java.util.Arrays; 8 | import java.util.List; 9 | import java.util.stream.Collectors; 10 | 11 | import javax.servlet.http.HttpServletRequest; 12 | 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.core.io.Resource; 15 | import org.springframework.http.HttpHeaders; 16 | import org.springframework.http.HttpStatus; 17 | import org.springframework.http.MediaType; 18 | import org.springframework.http.ResponseEntity; 19 | import org.springframework.web.bind.annotation.CrossOrigin; 20 | import org.springframework.web.bind.annotation.GetMapping; 21 | import org.springframework.web.bind.annotation.PathVariable; 22 | import org.springframework.web.bind.annotation.PostMapping; 23 | import org.springframework.web.bind.annotation.RequestMapping; 24 | import org.springframework.web.bind.annotation.RequestParam; 25 | import org.springframework.web.bind.annotation.RestController; 26 | import org.springframework.web.multipart.MultipartFile; 27 | import org.springframework.web.servlet.support.ServletUriComponentsBuilder; 28 | 29 | import com.sliit.af.exception.MyFileNotFoundException; 30 | import com.sliit.af.res.UploadFileResponse; 31 | import com.sliit.af.service.FileService; 32 | 33 | /** 34 | * @author vimukthi_r 35 | * 36 | */ 37 | @RestController 38 | @RequestMapping("/files") 39 | @CrossOrigin(origins = "*", allowedHeaders = "*") 40 | public class FileController { 41 | 42 | @Autowired 43 | private FileService fileService; 44 | 45 | @PostMapping("") 46 | public UploadFileResponse uploadFile(@RequestParam("file") MultipartFile file) { 47 | String fileName = null; 48 | String fileDownloadUri = null; 49 | UploadFileResponse uploadFileResponse = null; 50 | try { 51 | fileName = fileService.storeFile(file); 52 | 53 | fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath().path("/files/").path(fileName) 54 | .toUriString(); 55 | uploadFileResponse = new UploadFileResponse(fileName, fileDownloadUri, file.getContentType(), file.getSize()); 56 | } catch (Exception e) { 57 | // TODO Auto-generated catch block 58 | e.printStackTrace(); 59 | } 60 | 61 | return uploadFileResponse; 62 | } 63 | 64 | @PostMapping("/many") 65 | public List uploadMultipleFiles(@RequestParam("files") MultipartFile[] files) { 66 | List uploadFileResponses = null; 67 | try { 68 | uploadFileResponses = Arrays.asList(files).stream().map(file -> uploadFile(file)) 69 | .collect(Collectors.toList()); 70 | } catch (Exception e) { 71 | throw e; 72 | } 73 | return uploadFileResponses; 74 | } 75 | 76 | @GetMapping("/{fileName:.+}") 77 | public ResponseEntity downloadFile(@PathVariable String fileName, HttpServletRequest request) { 78 | String contentType = null; 79 | Resource resource = null; 80 | try { 81 | // Load file as Resource 82 | resource = fileService.loadFileAsResource(fileName); 83 | 84 | // Try to determine file's content type 85 | contentType = request.getServletContext().getMimeType(resource.getFile().getAbsolutePath()); 86 | } catch (MyFileNotFoundException ex) { 87 | return new ResponseEntity<>("File not found", HttpStatus.OK); 88 | } catch (IOException ex) { 89 | return new ResponseEntity<>("Sorry! something went wrong, try again.", HttpStatus.BAD_GATEWAY); 90 | } 91 | 92 | // Fallback to the default content type if type could not be determined 93 | if (contentType == null) { 94 | contentType = "application/octet-stream"; 95 | } 96 | 97 | return ResponseEntity.ok().contentType(MediaType.parseMediaType(contentType)) 98 | .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"") 99 | .body(resource); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /client/src/components/pages/CourseList.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import Filter from './sections/CourseBreadcrumSection' 3 | import { 4 | MDBCard, 5 | MDBCardBody, 6 | MDBCardHeader, 7 | MDBCol, 8 | MDBCollapse, 9 | MDBListGroup, 10 | MDBListGroupItem, 11 | MDBRow 12 | } from "mdbreact"; 13 | import CourseElement from './sections/CourseElement' 14 | import {courseByDegree} from '../functions/Services' 15 | 16 | export default class CourseList extends React.Component { 17 | 18 | state = { 19 | degree: '', 20 | collapseID: 'ss', 21 | year: '1st', 22 | semester: '1st', 23 | courses: [] 24 | } 25 | 26 | componentDidMount() { 27 | if (this.props.match && this.props.match.params) { 28 | const degree = this.props.match.params.id 29 | this.setState({degree: degree}, () => this.loadCourses()) 30 | } else { 31 | this.props.history.push('/faculties/404') 32 | } 33 | } 34 | 35 | loadCourses = () => { 36 | courseByDegree("dcode=" + this.state.degree + "&year=" + this.state.year + "&sem=" + this.state.semester) 37 | .then(res => { 38 | this.setState({courses: res.courses}) 39 | }) 40 | .catch(err => { 41 | console.log(err) 42 | }) 43 | } 44 | 45 | toggleCollapse = collapseID => () => { 46 | this.setState(prevState => ({ 47 | collapseID: prevState.collapseID !== collapseID ? collapseID : "" 48 | })); 49 | } 50 | 51 | handleChange = event => { 52 | let value = event; 53 | if (event.target) { 54 | value = event.target.value; 55 | } 56 | this.setState({[event.target.name]: value}, () => this.loadCourses()) 57 | } 58 | 59 | render() { 60 | return ( 61 | <> 62 | 67 | 68 | 69 | 70 | {this.state.year} Year, {this.state.semester} semester courses 71 | 72 | 73 | {this.state.courses.map((course, i) => { 74 | return ( 75 | 76 | 77 |
    {course.cname} 79 |
    81 |
    82 |
    83 | 84 | 85 | 86 |
    87 |
    88 | ) 89 | })} 90 |
    91 |
    92 |
    93 |
    94 |
    95 | 96 | ) 97 | } 98 | } -------------------------------------------------------------------------------- /client/src/components/functions/Services.js: -------------------------------------------------------------------------------- 1 | import config from './config.json' 2 | 3 | const nodeBaseUrl = config.nodeBaseUrl 4 | const springBaseUrl = config.springBaseUrl 5 | 6 | function getToken() { 7 | var user = localStorage.getItem('sis-user') 8 | if (user) { 9 | user = JSON.parse(user) 10 | return user.token 11 | } 12 | return null 13 | } 14 | 15 | export function updateAssignments(cid, aid, body) { 16 | return callPut(nodeBaseUrl + '/courses/' + cid + '/assignments/' + aid, body); 17 | } 18 | 19 | export function deleteAssignments(cid, aid) { 20 | return callDelete(nodeBaseUrl + '/courses/' + cid + '/assignments/' + aid); 21 | } 22 | 23 | export function getAssignments(id) { 24 | return callGet(nodeBaseUrl + '/courses/' + id + '/assignments'); 25 | } 26 | 27 | export function deleteCourseMaterials(cid, mid) { 28 | return callDelete(nodeBaseUrl + '/courses/' + cid + '/materials/' + mid); 29 | } 30 | 31 | export function getCourseMaterials(id) { 32 | return callGet(nodeBaseUrl + '/courses/' + id + '/materials'); 33 | } 34 | 35 | export function getFaculty(id) { 36 | return callGet(nodeBaseUrl + '/faculties/' + id); 37 | } 38 | 39 | export function getDegree(id) { 40 | return callGet(nodeBaseUrl + '/degrees/' + id); 41 | } 42 | 43 | export function getCourse(id) { 44 | return callGet(nodeBaseUrl + '/courses/course/' + id); 45 | } 46 | 47 | export function updateUser(body) { 48 | return callPut(springBaseUrl + '/users', body); 49 | } 50 | 51 | export function getFaculties() { 52 | return callGet(nodeBaseUrl + '/faculties/'); 53 | } 54 | 55 | export function searchCourse(name) { 56 | return callGet(nodeBaseUrl + '/courses/' + name); 57 | } 58 | 59 | export function getDegrees(id) { 60 | return callGet(nodeBaseUrl + '/faculties/' + id + '/degrees'); 61 | } 62 | 63 | export function courseByDegree(query) { 64 | return callGet(nodeBaseUrl + '/courses?' + query); 65 | } 66 | 67 | // export function login(body) { 68 | // return fetch(springBaseUrl + '/login', { 69 | // method: 'POST', 70 | // body: JSON.stringify(body), 71 | // headers: new Headers({ 72 | // 'Content-Type': 'application/json' 73 | // }) 74 | // }).then(handleres); 75 | // } 76 | 77 | export function register(body) { 78 | return fetch(springBaseUrl + '/users', { 79 | method: 'POST', 80 | body: JSON.stringify(body), 81 | headers: new Headers({ 82 | 'Content-Type': 'application/json' 83 | }) 84 | }).then(handleres); 85 | } 86 | 87 | const callGet = (url) => { 88 | return fetch(url, { 89 | method: 'GET', 90 | headers: new Headers({ 91 | 'Content-Type': 'application/json', 92 | 'Authorization': getToken() 93 | }) 94 | }).then(handleres); 95 | } 96 | 97 | // const callPost = (url, body) => { 98 | // return fetch(url, { 99 | // method: 'POST', 100 | // body: JSON.stringify(body), 101 | // headers: new Headers({ 102 | // 'Content-Type': 'application/json', 103 | // 'Authorization': getToken() 104 | // }) 105 | // }).then(handleres); 106 | // } 107 | 108 | const callPut = (url, body) => { 109 | return fetch(url, { 110 | method: 'PUT', 111 | body: JSON.stringify(body), 112 | headers: new Headers({ 113 | 'Content-Type': 'application/json', 114 | 'Authorization': getToken() 115 | }) 116 | }).then(handleres); 117 | } 118 | 119 | const callDelete = (url) => { 120 | return fetch(url, { 121 | method: 'DELETE', 122 | headers: new Headers({ 123 | 'Content-Type': 'application/json', 124 | 'Authorization': getToken() 125 | }) 126 | }).then(handleres); 127 | } 128 | 129 | const handleres = (res) => { 130 | if (res.ok) { 131 | return res.json(); 132 | } else { 133 | return Promise.reject(); 134 | } 135 | } -------------------------------------------------------------------------------- /client/src/components/pages/sections/SubmitAssignment.js: -------------------------------------------------------------------------------- 1 | import {Component} from "react"; 2 | import {MDBBtn, MDBCol, MDBIcon, MDBInput, MDBListGroupItem, MDBRow} from "mdbreact" 3 | import DatePicker from "react-datepicker" 4 | import {StyledDropzone} from "../../functions/StyledDropzone" 5 | import React from "react"; 6 | import config from "../../functions/config" 7 | import {toast} from "react-toastify" 8 | 9 | export default class SubmitAssignment extends Component { 10 | 11 | state = { 12 | showErr: false, 13 | errMsg: "Required fields empty or invalid", 14 | saved: false 15 | } 16 | 17 | getFiles = acceptedFiles => { 18 | const data = new FormData() 19 | for (var x = 0; x < acceptedFiles.length; x++) { 20 | data.append('files', acceptedFiles[x]) 21 | } 22 | this.setState({files: data, saved: true}) 23 | } 24 | 25 | handleSubmit = event => { 26 | if (this.state.files) { 27 | if (new Date() < new Date(this.props.assignment.dueDate)) { 28 | fetch(config.fileService + "/files/many", { 29 | method: 'POST', 30 | body: this.state.files, 31 | }).then(res => { 32 | return res.json() 33 | }).then(data => { 34 | toast.success("File uploaded") 35 | }).catch(err => { 36 | console.log(err) 37 | toast.error("Unable to add assignment") 38 | }) 39 | } else { 40 | toast.error("due date exceeded") 41 | } 42 | } else { 43 | toast.error("please select and save files or select data") 44 | } 45 | this.setState({showErr: false}) 46 | event.preventDefault() 47 | event.stopPropagation() 48 | } 49 | 50 | render() { 51 | return 52 | 53 | 54 | 63 | 64 | 65 |
    66 | 73 |
    74 |
    75 | 76 | { 77 | this.props.assignment.data.map((item, i) => { 78 | return 79 | 80 | 81 | {item.fileName} 82 | 83 | 84 | }) 85 | } 86 | 87 | 88 | 89 |

    Upload file name should 90 | be {this.props.cid}_{this.props.assignment.topic + "_.pdf"}

    91 |
    92 |
    93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | Upload answer 102 | 103 | 104 |
    ; 105 | } 106 | } -------------------------------------------------------------------------------- /client/src/components/pages/Profile.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import {MDBIcon, MDBCard, MDBCardBody, MDBCol, MDBCardHeader, MDBRow} from "mdbreact" 3 | import {getDegree, getCourse, getFaculty} from '../functions/Services' 4 | 5 | export default class Profile extends React.Component { 6 | 7 | state = { 8 | faculty: '', 9 | courses: [], 10 | degree: '', 11 | user: {} 12 | } 13 | 14 | componentDidMount() { 15 | var user = localStorage.getItem('sis-user') 16 | if (user) { 17 | user = JSON.parse(user) 18 | this.setState({user}) 19 | this.getFacultyName(user.faculty[0]) 20 | this.getDegreeName(user.degree[0]) 21 | if (user.courses) { 22 | this.getCourseName(user.courses) 23 | } 24 | } 25 | } 26 | 27 | getFacultyName = id => { 28 | getFaculty(id) 29 | .then(res => { 30 | this.setState({faculty: res.faculties[0].fname}) 31 | }) 32 | .catch(err => { 33 | console.log(err) 34 | }) 35 | } 36 | 37 | getDegreeName = id => { 38 | getDegree(id) 39 | .then(res => { 40 | this.setState({degree: res.degrees[0].dname}) 41 | }) 42 | .catch(err => { 43 | console.log(err) 44 | }) 45 | } 46 | 47 | getCourseName = ids => { 48 | ids.map(id => { 49 | return getCourse(id) 50 | .then(res => { 51 | this.setState({courses: [...this.state.courses, res.courses[0].cname]}) 52 | }) 53 | .catch(err => { 54 | console.log(err) 55 | }) 56 | }) 57 | 58 | } 59 | 60 | render() { 61 | 62 | return ( 63 | 64 | 65 | 66 | 67 |
    68 | 74 | {this.state.user.firstName + " " + this.state.user.lastName} 75 |
    76 |
    77 | 78 |
    79 |

    80 | 81 | Email : {this.state.user.email} 82 |

    83 |

    84 | 85 | Phone : {this.state.user.mobile} 86 |

    87 |

    88 | 89 | NIC : {this.state.user.nic} 90 |

    91 |

    92 | 93 | Address : {this.state.user.address} 94 |

    95 |
    96 |
    97 |

    98 | 99 | Faculty : {this.state.faculty} 100 |

    101 |

    102 | 103 | Degree : {this.state.degree} 104 |

    105 |

    106 | 107 | My Courses : {this.state.courses.join(", ")} 108 |

    109 |
    110 |
    111 |
    112 |
    113 | ) 114 | } 115 | } -------------------------------------------------------------------------------- /client/src/index.css: -------------------------------------------------------------------------------- 1 | body{ 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; 4 | font-size: 1rem; 5 | font-weight: 400; 6 | line-height: 1.5; 7 | color: #212529; 8 | text-align: left; 9 | background-color: #EDEDEE; 10 | } 11 | 12 | a{ 13 | color: inherit; 14 | } 15 | 16 | .list-group-flush{ 17 | color: #495057; 18 | } 19 | 20 | .active{ 21 | background-color: #e9ecef; 22 | } 23 | 24 | main { 25 | background-color: #EDEDEE; 26 | } 27 | 28 | .navbar-brand{ 29 | margin-left: 15px; 30 | color: #2196f3 !important; 31 | } 32 | 33 | .sidebar-fixed { 34 | left: 0; 35 | top: 0; 36 | height: 100vh; 37 | width: 270px; 38 | box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12); 39 | z-index: 1050; 40 | background-color: #fff; 41 | padding: 1.5rem; 42 | padding-top: 0; 43 | } 44 | 45 | 46 | .flexible-navbar { 47 | transition: padding-left 0.5s; 48 | padding-left: 270px; 49 | background: #fff; 50 | } 51 | 52 | #content{ 53 | margin-left: 270px; 54 | } 55 | 56 | 57 | .sidebar-fixed .logo-wrapper img{ 58 | width: 100%; 59 | padding: 2.5rem; 60 | } 61 | 62 | .list-group-item { 63 | display: block !important; 64 | transition: background-color 0.3s; 65 | } 66 | 67 | .list-group-item:hover { 68 | color: #49505B; 69 | text-decoration: none; 70 | background-color: #f8f9fa 71 | } 72 | 73 | .list-group-item:hover { 74 | color: #49505B; 75 | text-decoration: none; 76 | background-color: #f8f9fa 77 | } 78 | 79 | 80 | .list-group .active { 81 | box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12); 82 | border-radius: 5px; 83 | } 84 | 85 | .card-title{ 86 | font-size: 1.5rem; 87 | font-weight: 600; 88 | } 89 | 90 | .card-subtitle{ 91 | font-size: 1.25rem; 92 | font-weight: 600; 93 | } 94 | 95 | .full { 96 | height: 70vh; 97 | } 98 | 99 | .bad-gateway-row { 100 | margin: 0; 101 | position: absolute; 102 | top: 50%; 103 | left: 55%; 104 | -webkit-transform: translate(-50%, -50%); 105 | transform: translate(-50%, -50%); 106 | } 107 | 108 | 109 | .card .view.gradient-card-header { 110 | padding: 1rem 1rem; 111 | text-align: center; 112 | } 113 | 114 | .card h3, .card.card-cascade h4 { 115 | margin-bottom: 0px; 116 | } 117 | 118 | .cascading-admin-card .admin-up { 119 | margin-left: 4%; 120 | margin-right: 4%; 121 | margin-top: -20px; 122 | } 123 | 124 | .cascading-admin-card .admin-up .fa { 125 | box-shadow: 0 2px 9px 0 rgba(0, 0, 0, 0.2), 0 2px 13px 0 rgba(0, 0, 0, 0.19); 126 | } 127 | 128 | .cascading-admin-card .admin-up .fa { 129 | padding: 1.7rem; 130 | font-size: 2rem; 131 | color: #fff; 132 | text-align: left; 133 | margin-right: 1rem; 134 | border-radius: 3px; 135 | } 136 | 137 | .cascading-admin-card .admin-up .data { 138 | float: right; 139 | margin-top: 2rem; 140 | text-align: right; 141 | } 142 | .admin-up .data p { 143 | color: #999999; 144 | font-size: 12px; 145 | } 146 | .classic-admin-card .card-body { 147 | color: #fff; 148 | margin-bottom: 0; 149 | padding: 0.9rem; 150 | } 151 | .classic-admin-card .card-body p { 152 | font-size: 13px; 153 | opacity: 0.7; 154 | margin-bottom: 0; 155 | } 156 | .classic-admin-card .card-body h4 { 157 | margin-top: 10px; 158 | } 159 | 160 | .form-inline{ 161 | flex-flow: unset 162 | } 163 | 164 | .breadcrumb{ 165 | margin: 0; 166 | } 167 | 168 | .activeClass .list-group-item { 169 | z-index: 5; 170 | color: #fff; 171 | border-color: #007bff; 172 | box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12); 173 | border-radius: 5px !important; 174 | background-color: #007bff !important; 175 | } 176 | 177 | .page-footer{ 178 | margin-left: 270px; 179 | } 180 | 181 | @media (max-width: 1199.98px) { 182 | .sidebar-fixed { 183 | display: none; 184 | } 185 | .flexible-content { 186 | padding-left: 0; 187 | } 188 | .flexible-navbar { 189 | padding-left: 10px; 190 | } 191 | 192 | #content{ 193 | margin-left: 0px; 194 | } 195 | 196 | .page-footer{ 197 | margin-left: 0px; 198 | } 199 | 200 | .card.cascading-admin-card { 201 | margin-top: 2.5rem; 202 | } 203 | } 204 | 205 | @media (max-width: 576px) { 206 | .card.cascading-admin-card { 207 | margin-top: 2.5rem; 208 | } 209 | 210 | #breadcrumb{ 211 | flex-direction: column; 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /services/spring-boot/student-information-service/src/test/java/com/sliit/af/studentinformationservice/serviceTests/UserServiceTests.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.sliit.af.studentinformationservice.serviceTests; 5 | 6 | import static org.assertj.core.api.Assertions.assertThat; 7 | import static org.hamcrest.CoreMatchers.is; 8 | import static org.junit.Assert.assertThat; 9 | 10 | import java.util.Arrays; 11 | import java.util.HashSet; 12 | import java.util.List; 13 | import java.util.Optional; 14 | 15 | import org.junit.Before; 16 | import org.junit.Test; 17 | import org.junit.runner.RunWith; 18 | import org.mockito.Mockito; 19 | import org.springframework.beans.factory.annotation.Autowired; 20 | import org.springframework.boot.test.context.TestConfiguration; 21 | import org.springframework.boot.test.mock.mockito.MockBean; 22 | import org.springframework.context.annotation.Bean; 23 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 24 | import org.springframework.test.context.junit4.SpringRunner; 25 | 26 | import com.sliit.af.domain.UserDTO; 27 | import com.sliit.af.model.Role; 28 | import com.sliit.af.model.User; 29 | import com.sliit.af.repository.RoleRepository; 30 | import com.sliit.af.repository.UserRepository; 31 | import com.sliit.af.service.UserService; 32 | import com.sliit.af.service.impl.UserServiceImpl; 33 | 34 | /** 35 | * @author Vimukthi_r 36 | * 37 | */ 38 | @RunWith(SpringRunner.class) 39 | public class UserServiceTests { 40 | 41 | @TestConfiguration 42 | public static class UserServiceImplTestConfiguration { 43 | 44 | @Bean 45 | public UserService userService() { 46 | return new UserServiceImpl(); 47 | } 48 | 49 | @Bean 50 | public BCryptPasswordEncoder bCryptPasswordEncoder() { 51 | return new BCryptPasswordEncoder(); 52 | } 53 | } 54 | 55 | @Autowired 56 | UserService userService; 57 | @MockBean 58 | UserRepository userRepository; 59 | @MockBean 60 | RoleRepository roleRepository; 61 | 62 | @Before 63 | public void setup() { 64 | User user = new User(); 65 | User user1 = new User(); 66 | User user2 = new User(); 67 | Role role = new Role("1", "Admin"); 68 | 69 | user.setId("1"); 70 | user.setEmail("user@user.com"); 71 | user.setPassword("password"); 72 | 73 | user1.setEmail("user1@user.com"); 74 | user1.setPassword("password1"); 75 | 76 | user2.setId("3"); 77 | user2.setEmail("user2@user.com"); 78 | user2.setPassword("password2"); 79 | 80 | User userWithId = user1; 81 | userWithId.setId("2"); 82 | userWithId.setRoles(new HashSet<>(Arrays.asList(role))); 83 | 84 | Mockito.when(userRepository.findById("1")).thenReturn(Optional.of(user)); 85 | Mockito.when(userRepository.findByEmailAndPassword("user@user.com", "password")).thenReturn(Optional.of(user)); 86 | Mockito.when(userRepository.findByEmail("user@user.com")).thenReturn(Optional.of(user)); 87 | Mockito.when(userRepository.findAll()).thenReturn(Arrays.asList(user, user1, user2)); 88 | Mockito.when(userRepository.save(user1)).thenReturn(userWithId); 89 | } 90 | 91 | @Test 92 | public void whenUserId_thenUserBeanShouldReturn() { 93 | assertThat(userService.getUserById("1")).hasFieldOrPropertyWithValue("email", "user@user.com"); 94 | } 95 | 96 | @Test 97 | public void whenInvalidUserId_thenNullShouldReturn() { 98 | assertThat(userService.getUserById("10")).isEqualTo(null); 99 | } 100 | 101 | @Test 102 | public void whenFindAll_thenUserBeansListShouldReturn() { 103 | List List = userService.getAll(); 104 | User lastUserBean = null; 105 | for (User user : List) { 106 | lastUserBean = user; 107 | } 108 | assertThat(List).hasSize(3); 109 | assertThat(lastUserBean).hasFieldOrPropertyWithValue("email", "user2@user.com"); 110 | } 111 | 112 | @Test 113 | public void whenFindByEmailAndPassword_thenUserBeanShouldReturn() { 114 | UserDTO userDTO = new UserDTO("user@user.com", "password"); 115 | assertThat(userService.getByEmailAndPassword(userDTO)).hasFieldOrPropertyWithValue("email", "user@user.com"); 116 | } 117 | 118 | @Test 119 | public void whenInvalidEmailAndPassword_thenNullShouldReturn() { 120 | UserDTO userDTO = new UserDTO("noUser@user.com", "password"); 121 | assertThat(userService.getByEmailAndPassword(userDTO)).isEqualTo(null); 122 | } 123 | 124 | @Test 125 | public void whenFindByEmail_thenUserBeanShouldReturn() { 126 | assertThat(userService.getByEmail("user@user.com")).hasFieldOrPropertyWithValue("email", "user@user.com"); 127 | } 128 | 129 | @Test 130 | public void whenInvalidEmail_thenNullShouldReturn() { 131 | assertThat(userService.getByEmail("userNo@user.com")).isEqualTo(null); 132 | } 133 | 134 | @Test 135 | public void whenRequestForAll_thenAllUsersShouldReturn() { 136 | assertThat(userService.getAll().size(), is(3)); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /services/spring-boot/file-manage-service/.mvn/wrapper/MavenWrapperDownloader.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | https://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | import java.io.File; 21 | import java.io.FileInputStream; 22 | import java.io.FileOutputStream; 23 | import java.io.IOException; 24 | import java.net.URL; 25 | import java.nio.channels.Channels; 26 | import java.nio.channels.ReadableByteChannel; 27 | import java.util.Properties; 28 | 29 | public class MavenWrapperDownloader { 30 | 31 | /** 32 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. 33 | */ 34 | private static final String DEFAULT_DOWNLOAD_URL = 35 | "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"; 36 | 37 | /** 38 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to 39 | * use instead of the default one. 40 | */ 41 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH = 42 | ".mvn/wrapper/maven-wrapper.properties"; 43 | 44 | /** 45 | * Path where the maven-wrapper.jar will be saved to. 46 | */ 47 | private static final String MAVEN_WRAPPER_JAR_PATH = 48 | ".mvn/wrapper/maven-wrapper.jar"; 49 | 50 | /** 51 | * Name of the property which should be used to override the default download url for the wrapper. 52 | */ 53 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; 54 | 55 | public static void main(String args[]) { 56 | System.out.println("- Downloader started"); 57 | File baseDirectory = new File(args[0]); 58 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); 59 | 60 | // If the maven-wrapper.properties exists, read it and check if it contains a custom 61 | // wrapperUrl parameter. 62 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); 63 | String url = DEFAULT_DOWNLOAD_URL; 64 | if(mavenWrapperPropertyFile.exists()) { 65 | FileInputStream mavenWrapperPropertyFileInputStream = null; 66 | try { 67 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); 68 | Properties mavenWrapperProperties = new Properties(); 69 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); 70 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); 71 | } catch (IOException e) { 72 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); 73 | } finally { 74 | try { 75 | if(mavenWrapperPropertyFileInputStream != null) { 76 | mavenWrapperPropertyFileInputStream.close(); 77 | } 78 | } catch (IOException e) { 79 | // Ignore ... 80 | } 81 | } 82 | } 83 | System.out.println("- Downloading from: : " + url); 84 | 85 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); 86 | if(!outputFile.getParentFile().exists()) { 87 | if(!outputFile.getParentFile().mkdirs()) { 88 | System.out.println( 89 | "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'"); 90 | } 91 | } 92 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); 93 | try { 94 | downloadFileFromURL(url, outputFile); 95 | System.out.println("Done"); 96 | System.exit(0); 97 | } catch (Throwable e) { 98 | System.out.println("- Error downloading"); 99 | e.printStackTrace(); 100 | System.exit(1); 101 | } 102 | } 103 | 104 | private static void downloadFileFromURL(String urlString, File destination) throws Exception { 105 | URL website = new URL(urlString); 106 | ReadableByteChannel rbc; 107 | rbc = Channels.newChannel(website.openStream()); 108 | FileOutputStream fos = new FileOutputStream(destination); 109 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); 110 | fos.close(); 111 | rbc.close(); 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /services/spring-boot/student-information-service/.mvn/wrapper/MavenWrapperDownloader.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | https://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | import java.io.File; 21 | import java.io.FileInputStream; 22 | import java.io.FileOutputStream; 23 | import java.io.IOException; 24 | import java.net.URL; 25 | import java.nio.channels.Channels; 26 | import java.nio.channels.ReadableByteChannel; 27 | import java.util.Properties; 28 | 29 | public class MavenWrapperDownloader { 30 | 31 | /** 32 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. 33 | */ 34 | private static final String DEFAULT_DOWNLOAD_URL = 35 | "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"; 36 | 37 | /** 38 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to 39 | * use instead of the default one. 40 | */ 41 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH = 42 | ".mvn/wrapper/maven-wrapper.properties"; 43 | 44 | /** 45 | * Path where the maven-wrapper.jar will be saved to. 46 | */ 47 | private static final String MAVEN_WRAPPER_JAR_PATH = 48 | ".mvn/wrapper/maven-wrapper.jar"; 49 | 50 | /** 51 | * Name of the property which should be used to override the default download url for the wrapper. 52 | */ 53 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; 54 | 55 | public static void main(String args[]) { 56 | System.out.println("- Downloader started"); 57 | File baseDirectory = new File(args[0]); 58 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); 59 | 60 | // If the maven-wrapper.properties exists, read it and check if it contains a custom 61 | // wrapperUrl parameter. 62 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); 63 | String url = DEFAULT_DOWNLOAD_URL; 64 | if(mavenWrapperPropertyFile.exists()) { 65 | FileInputStream mavenWrapperPropertyFileInputStream = null; 66 | try { 67 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); 68 | Properties mavenWrapperProperties = new Properties(); 69 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); 70 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); 71 | } catch (IOException e) { 72 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); 73 | } finally { 74 | try { 75 | if(mavenWrapperPropertyFileInputStream != null) { 76 | mavenWrapperPropertyFileInputStream.close(); 77 | } 78 | } catch (IOException e) { 79 | // Ignore ... 80 | } 81 | } 82 | } 83 | System.out.println("- Downloading from: : " + url); 84 | 85 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); 86 | if(!outputFile.getParentFile().exists()) { 87 | if(!outputFile.getParentFile().mkdirs()) { 88 | System.out.println( 89 | "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'"); 90 | } 91 | } 92 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); 93 | try { 94 | downloadFileFromURL(url, outputFile); 95 | System.out.println("Done"); 96 | System.exit(0); 97 | } catch (Throwable e) { 98 | System.out.println("- Error downloading"); 99 | e.printStackTrace(); 100 | System.exit(1); 101 | } 102 | } 103 | 104 | private static void downloadFileFromURL(String urlString, File destination) throws Exception { 105 | URL website = new URL(urlString); 106 | ReadableByteChannel rbc; 107 | rbc = Channels.newChannel(website.openStream()); 108 | FileOutputStream fos = new FileOutputStream(destination); 109 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); 110 | fos.close(); 111 | rbc.close(); 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /client/src/components/TopNavigation.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react' 2 | import { 3 | MDBNavbar, 4 | MDBFormInline, 5 | MDBNavbarNav, 6 | MDBNavbarToggler, 7 | MDBCollapse, 8 | MDBNavItem, 9 | MDBNavLink, 10 | MDBDropdown, 11 | MDBDropdownToggle, 12 | MDBDropdownMenu, 13 | MDBIcon, 14 | MDBDropdownItem 15 | } from 'mdbreact' 16 | import Login from './modals/Login' 17 | 18 | class TopNavigation extends Component { 19 | state = { 20 | modal: false, 21 | searchVal: '' 22 | } 23 | 24 | toggle = () => { 25 | this.setState({ 26 | modal: !this.state.modal 27 | }); 28 | } 29 | 30 | courseSearch = event => { 31 | event.preventDefault() 32 | event.stopPropagation() 33 | if (this.state.searchVal) { 34 | window.location = '/courses/search?name=' + this.state.searchVal 35 | } 36 | } 37 | 38 | logout = () => { 39 | localStorage.clear() 40 | window.location = '/' 41 | } 42 | 43 | render() { 44 | var user = localStorage.getItem('sis-user') 45 | if (user) { 46 | user = JSON.parse(user) 47 | } 48 | return ( 49 | <> 50 | 51 | 52 | 53 | 54 | 55 | Home 56 | 57 | 58 | About 59 | 60 | 61 | Contact 62 | 63 | 64 | 65 | {user ? 66 | <> 67 | 68 | 69 |
    70 | this.setState({searchVal: e.target.value})}/> 74 |
    75 |
    76 |
    77 | 78 | 79 | 80 | {user.firstName} 81 | 82 | 83 | Profile 84 | 85 | Sign 86 | out 87 | 88 | 89 | 90 | 91 | : 92 | <> 93 | 94 | Sign 96 | up 97 | 98 | 99 | this.toggle()}>Log in 101 | 102 | 103 | } 104 |
    105 |
    106 |
    107 | 111 | 112 | ); 113 | } 114 | } 115 | 116 | export default TopNavigation; -------------------------------------------------------------------------------- /services/node/controller/facultyController.js: -------------------------------------------------------------------------------- 1 | const express = require("express") 2 | const route = express.Router() 3 | const jwt = require("jsonwebtoken") 4 | const Faculties = require("../model/faculties") 5 | const Degrees = require("../model/degrees") 6 | const tf = require("../verifyToken") 7 | const config = require("../config.json") 8 | 9 | 10 | //faculty creation 11 | route.post("/", tf.verifyToken, (req, res) => { 12 | 13 | jwt.verify(req.token, config.secret, (err, authData) => { 14 | if (err) { 15 | res.status(403).json({ status: "forbidden" }) 16 | } else { 17 | try { 18 | const query = { $or: [{ fname: req.body.fname }, { fcode: req.body.fcode }] } 19 | Faculties.find(query, (err, faculty) => { 20 | if (err) { 21 | console.log(err); 22 | res.status(500).json({ error: err }); 23 | } else { 24 | if (faculty.length != 0) { 25 | res.status(200).json({ facultyExist: true }); 26 | } else { 27 | let faculties = new Faculties(req.body); 28 | faculties.save(err => { 29 | if (err) { 30 | console.log(err); 31 | res.status(500).json({ error: err }); 32 | } else { 33 | res.status(201).json({ facultyExist: false }); 34 | } 35 | }); 36 | } 37 | } 38 | }); 39 | } catch (ex) { 40 | res.status(500).send("Server Error" + ex) 41 | } 42 | } 43 | }) 44 | 45 | }) 46 | 47 | //get all faculties 48 | route.get("/", (req, res) => { 49 | 50 | try { 51 | const query = {} 52 | Faculties.find(query, (err, faculty) => { 53 | if (err) { 54 | console.log(err); 55 | res.status(500).json({ error: err }); 56 | } else { 57 | res.status(200).json({ faculties: faculty }) 58 | } 59 | }); 60 | } catch (ex) { 61 | res.status(500).send("Server Error" + ex) 62 | } 63 | 64 | }) 65 | 66 | //get faculty by code 67 | route.get("/:code", (req, res) => { 68 | 69 | try { 70 | const query = { fcode: req.params.code } 71 | Faculties.find(query, (err, faculty) => { 72 | if (err) { 73 | console.log(err); 74 | res.status(500).json({ error: err }); 75 | } else { 76 | res.status(200).json({ faculties: faculty }) 77 | } 78 | }); 79 | } catch (ex) { 80 | res.status(500).send("Server Error" + ex) 81 | } 82 | 83 | }) 84 | 85 | //update faculties 86 | route.put("/:code", tf.verifyToken, (req, res) => { 87 | 88 | jwt.verify(req.token, config.secret, (err, authData) => { 89 | if (err) { 90 | res.status(403).json({ status: "forbidden" }) 91 | } else { 92 | try { 93 | const query = { fcode: req.params.code } 94 | Faculties.updateOne(query, req.body, (err) => { 95 | if (err) { 96 | console.log(err) 97 | res.status(500).json({ error: err }); 98 | } else { 99 | res.status(200).json({ status: true }) 100 | } 101 | }) 102 | } catch (ex) { 103 | res.status(500).send("Server Error" + ex) 104 | } 105 | } 106 | }) 107 | 108 | }) 109 | 110 | //delete faculties 111 | route.delete("/:code", tf.verifyToken, (req, res) => { 112 | 113 | jwt.verify(req.token, config.secret, (err, authData) => { 114 | if (err) { 115 | res.status(403).json({ status: "forbidden" }) 116 | } else { 117 | try { 118 | const query = { fcode: req.params.code } 119 | Faculties.deleteOne(query, (err) => { 120 | if (err) { 121 | console.log(err) 122 | res.status(500).json({ error: err }); 123 | } else { 124 | res.status(200).json({ status: true }) 125 | } 126 | }) 127 | } catch (ex) { 128 | res.status(500).send("Server Error" + ex) 129 | } 130 | } 131 | }) 132 | 133 | }) 134 | 135 | //get degrees of particular course 136 | //eg :- localhost:4000/faculties/IT/degrees 137 | route.get("/:code/degrees", tf.verifyToken, (req, res) => { 138 | 139 | try { 140 | const query = { fcode: req.params.code } 141 | Degrees.find(query, (err, degree) => { 142 | if (err) { 143 | console.log(err); 144 | res.status(500).json({ error: err }); 145 | } else { 146 | res.status(200).json({ degrees: degree }) 147 | } 148 | }); 149 | } catch (ex) { 150 | res.status(500).send("Server Error" + ex) 151 | } 152 | 153 | }) 154 | 155 | 156 | module.exports = route 157 | 158 | -------------------------------------------------------------------------------- /client/src/components/pages/sections/CourseMaterials.js: -------------------------------------------------------------------------------- 1 | import {Component} from "react"; 2 | import { 3 | MDBBtn, 4 | MDBCard, 5 | MDBCardHeader, 6 | MDBCol, 7 | MDBRow, 8 | MDBListGroupItem, 9 | MDBListGroup, MDBIcon 10 | } from "mdbreact"; 11 | import React from "react"; 12 | import {StyledDropzone} from "../../functions/StyledDropzone" 13 | import config from "../../functions/config" 14 | import {getCourseMaterials, deleteCourseMaterials} from "../../functions/Services" 15 | import {toast} from "react-toastify"; 16 | 17 | export default class CourseMaterials extends Component { 18 | 19 | state = { 20 | saved: false, 21 | materials: [], 22 | } 23 | 24 | componentDidMount() { 25 | setTimeout(() => this.getMeterials(), 400) 26 | } 27 | 28 | handleSubmit = event => { 29 | if (this.state.files) { 30 | fetch(config.fileService + "/files/many", { 31 | method: 'POST', 32 | body: this.state.files, 33 | }).then(res => { 34 | return res.json() 35 | }).then(data => { 36 | fetch(config.nodeBaseUrl + '/courses/' + this.props.cid + "/materials", { 37 | method: 'POST', 38 | body: JSON.stringify({data: data}), 39 | headers: new Headers({ 40 | 'Content-Type': 'application/json' 41 | }) 42 | }).then(res => { 43 | toast.success("Successfully added course materials") 44 | this.getMeterials() 45 | }) 46 | }).catch(err => { 47 | console.log(err) 48 | toast.error("Unable to add course materials") 49 | }) 50 | } else { 51 | toast.error("please select and save files") 52 | } 53 | event.preventDefault() 54 | event.stopPropagation() 55 | } 56 | 57 | handleDelete = (id) => { 58 | deleteCourseMaterials(this.props.cid, id) 59 | .then(res => { 60 | this.getMeterials() 61 | toast.success("Successfully deleted course materials") 62 | }) 63 | .catch(err => { 64 | console.log(err) 65 | toast.error("Unable to delete course materials") 66 | }) 67 | } 68 | 69 | getMeterials = () => { 70 | getCourseMaterials(this.props.cid) 71 | .then(async res => { 72 | var materials = [] 73 | await res.materials.map((item, i) => { 74 | return materials.push( 75 | 76 | 77 | 78 | 79 | {item.fileName} 80 | 81 | 82 | this.handleDelete(item.fileName)}>Delete 84 | 85 | 86 | 87 | ) 88 | }) 89 | this.setState({materials: materials}) 90 | }) 91 | .catch(err => { 92 | console.log(err) 93 | }) 94 | } 95 | 96 | getFiles = acceptedFiles => { 97 | const data = new FormData() 98 | for (var x = 0; x < acceptedFiles.length; x++) { 99 | data.append('files', acceptedFiles[x]) 100 | } 101 | this.setState({files: data, saved: true}) 102 | } 103 | 104 | render() { 105 | return
    106 | 107 | 108 | 109 | Course Materials 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | Upload 121 | 122 | 123 | 124 | 125 | 126 | {this.state.materials} 127 | 128 | 129 | 130 | 131 |
    ; 132 | } 133 | } -------------------------------------------------------------------------------- /client/src/serviceWorker.js: -------------------------------------------------------------------------------- 1 | // This optional code is used to register a service worker. 2 | // register() is not called by default. 3 | 4 | // This lets the app load faster on subsequent visits in production, and gives 5 | // it offline capabilities. However, it also means that developers (and users) 6 | // will only see deployed updates on subsequent visits to a page, after all the 7 | // existing tabs open on the page have been closed, since previously cached 8 | // resources are updated in the background. 9 | 10 | // To learn more about the benefits of this model and instructions on how to 11 | // opt-in, read https://bit.ly/CRA-PWA 12 | 13 | const isLocalhost = Boolean( 14 | window.location.hostname === 'localhost' || 15 | // [::1] is the IPv6 localhost address. 16 | window.location.hostname === '[::1]' || 17 | // 127.0.0.1/8 is considered localhost for IPv4. 18 | window.location.hostname.match( 19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ 20 | ) 21 | ); 22 | 23 | export function register(config) { 24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { 25 | // The URL constructor is available in all browsers that support SW. 26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); 27 | if (publicUrl.origin !== window.location.origin) { 28 | // Our service worker won't work if PUBLIC_URL is on a different origin 29 | // from what our page is served on. This might happen if a CDN is used to 30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374 31 | return; 32 | } 33 | 34 | window.addEventListener('load', () => { 35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; 36 | 37 | if (isLocalhost) { 38 | // This is running on localhost. Let's check if a service worker still exists or not. 39 | checkValidServiceWorker(swUrl, config); 40 | 41 | // Add some additional logging to localhost, pointing developers to the 42 | // service worker/PWA documentation. 43 | navigator.serviceWorker.ready.then(() => { 44 | console.log( 45 | 'This web app is being served cache-first by a service ' + 46 | 'worker. To learn more, visit https://bit.ly/CRA-PWA' 47 | ); 48 | }); 49 | } else { 50 | // Is not localhost. Just register service worker 51 | registerValidSW(swUrl, config); 52 | } 53 | }); 54 | } 55 | } 56 | 57 | function registerValidSW(swUrl, config) { 58 | navigator.serviceWorker 59 | .register(swUrl) 60 | .then(registration => { 61 | registration.onupdatefound = () => { 62 | const installingWorker = registration.installing; 63 | if (installingWorker == null) { 64 | return; 65 | } 66 | installingWorker.onstatechange = () => { 67 | if (installingWorker.state === 'installed') { 68 | if (navigator.serviceWorker.controller) { 69 | // At this point, the updated precached content has been fetched, 70 | // but the previous service worker will still serve the older 71 | // content until all client tabs are closed. 72 | console.log( 73 | 'New content is available and will be used when all ' + 74 | 'tabs for this page are closed. See https://bit.ly/CRA-PWA.' 75 | ); 76 | 77 | // Execute callback 78 | if (config && config.onUpdate) { 79 | config.onUpdate(registration); 80 | } 81 | } else { 82 | // At this point, everything has been precached. 83 | // It's the perfect time to display a 84 | // "Content is cached for offline use." message. 85 | console.log('Content is cached for offline use.'); 86 | 87 | // Execute callback 88 | if (config && config.onSuccess) { 89 | config.onSuccess(registration); 90 | } 91 | } 92 | } 93 | }; 94 | }; 95 | }) 96 | .catch(error => { 97 | console.error('Error during service worker registration:', error); 98 | }); 99 | } 100 | 101 | function checkValidServiceWorker(swUrl, config) { 102 | // Check if the service worker can be found. If it can't reload the page. 103 | fetch(swUrl) 104 | .then(response => { 105 | // Ensure service worker exists, and that we really are getting a JS file. 106 | const contentType = response.headers.get('content-type'); 107 | if ( 108 | response.status === 404 || 109 | (contentType != null && contentType.indexOf('javascript') === -1) 110 | ) { 111 | // No service worker found. Probably a different app. Reload the page. 112 | navigator.serviceWorker.ready.then(registration => { 113 | registration.unregister().then(() => { 114 | window.location.reload(); 115 | }); 116 | }); 117 | } else { 118 | // Service worker found. Proceed as normal. 119 | registerValidSW(swUrl, config); 120 | } 121 | }) 122 | .catch(() => { 123 | console.log( 124 | 'No internet connection found. App is running in offline mode.' 125 | ); 126 | }); 127 | } 128 | 129 | export function unregister() { 130 | if ('serviceWorker' in navigator) { 131 | navigator.serviceWorker.ready.then(registration => { 132 | registration.unregister(); 133 | }); 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /client/src/components/modals/Login.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react' 2 | 3 | import { 4 | MDBModal, 5 | MDBBtn, 6 | MDBInput, 7 | MDBRow, 8 | MDBCol, 9 | MDBCard, 10 | MDBCardBody 11 | } from 'mdbreact' 12 | import {getHash} from '../functions/Functions' 13 | import config from '../functions/config.json' 14 | 15 | class Login extends Component { 16 | 17 | constructor(props, context) { 18 | super(props, context) 19 | this.state = { 20 | MDBModalShowErr: false, 21 | MDBModalErrMsg: "Incorrect username or password!!!", 22 | username: "", 23 | password: "" 24 | } 25 | this.baseState = this.state 26 | } 27 | 28 | componentWillUnmount() { 29 | this.setState(this.baseState) 30 | } 31 | 32 | handleChange = event => { 33 | let value = event; 34 | if (event.target) { 35 | value = event.target.value; 36 | } 37 | this.setState({[event.target.name]: value}) 38 | } 39 | 40 | handleSubmit = event => { 41 | this.setState({MDBModalShowErr: false}) 42 | 43 | const body = { 44 | email: this.state.email, 45 | password: getHash(this.state.password) 46 | } 47 | 48 | fetch(config.springBaseUrl + '/login', { 49 | method: 'POST', 50 | body: JSON.stringify(body), 51 | headers: new Headers({ 52 | 'Content-Type': 'application/json' 53 | }) 54 | }) 55 | .then(res => { 56 | const auth = res.headers.get('authorization') 57 | return res.json().then(r => { 58 | return {...r, token: auth} 59 | }) 60 | }).then(data => { 61 | localStorage.setItem('sis-user', JSON.stringify(data)) 62 | window.location = "/" 63 | this.props.toggle() 64 | }).catch(err => { 65 | console.log(err) 66 | this.setState({MDBModalShowErr: true}) 67 | }) 68 | 69 | event.preventDefault() 70 | event.stopPropagation() 71 | } 72 | 73 | render() { 74 | return ( 75 | 76 | 77 | 78 | 79 |
    80 | 81 |

    82 | Log in 83 |

    84 |
    85 |
    86 | 87 |
    88 | 96 | 107 | 108 | 109 | {this.state.MDBModalShowErr && 110 |

    {this.state.MDBModalErrMsg}

    } 111 |
    112 |
    113 |
    114 | 119 | Log in 120 | 121 |
    122 |

    123 | Don't have an account? 124 | 128 | Sign up 129 | 130 |

    131 | 132 |
    133 |
    134 |
    135 |
    136 |
    137 | ); 138 | } 139 | } 140 | 141 | export default Login; -------------------------------------------------------------------------------- /services/node/controller/degreeController.js: -------------------------------------------------------------------------------- 1 | const express = require("express") 2 | const route = express.Router() 3 | const jwt = require("jsonwebtoken") 4 | const Degrees = require("../model/degrees") 5 | const Courses = require("../model/courses") 6 | const tf = require("../verifyToken") 7 | const config = require("../config.json") 8 | 9 | //degree creation 10 | route.post("/", tf.verifyToken, (req, res) => { 11 | 12 | jwt.verify(req.token, config.secret, (err, authData) => { 13 | if (err) { 14 | res.status(403).json({ status: "forbidden" }) 15 | } else { 16 | try { 17 | const query = { $or: [{ dname: req.body.dname }, { dcode: req.body.dcode }] } 18 | Degrees.find(query, (err, degree) => { 19 | if (err) { 20 | console.log(err); 21 | res.status(500).json({ error: err }); 22 | } else { 23 | if (degree.length != 0) { 24 | res.status(200).json({ degreeExist: true }); 25 | } else { 26 | let degrees = new Degrees(req.body); 27 | degrees.save(err => { 28 | if (err) { 29 | console.log(err); 30 | res.status(500).json({ error: err }); 31 | } else { 32 | res.status(201).json({ degreeExist: false }); 33 | } 34 | }); 35 | } 36 | } 37 | }); 38 | } catch (ex) { 39 | res.status(500).send("Server Error" + ex) 40 | } 41 | } 42 | }) 43 | 44 | }); 45 | 46 | //get all degrees 47 | route.get("/", tf.verifyToken, (req, res) => { 48 | 49 | jwt.verify(req.token, config.secret, (err, authData) => { 50 | if (err) { 51 | res.status(403).json({ status: "forbidden" }) 52 | } else { 53 | try { 54 | const query = {} 55 | Degrees.find(query, (err, degree) => { 56 | if (err) { 57 | console.log(err); 58 | res.status(500).json({ error: err }); 59 | } else { 60 | res.status(200).json({ degrees: degree }) 61 | } 62 | }); 63 | } catch (ex) { 64 | res.status(500).send("Server Error" + ex) 65 | } 66 | } 67 | }) 68 | 69 | }) 70 | 71 | //get degree by code 72 | route.get("/:code", (req, res) => { 73 | 74 | try { 75 | const query = { dcode: req.params.code } 76 | Degrees.find(query, (err, degree) => { 77 | if (err) { 78 | console.log(err); 79 | res.status(500).json({ error: err }); 80 | } else { 81 | res.status(200).json({ degrees: degree }) 82 | } 83 | }); 84 | } catch (ex) { 85 | res.status(500).send("Server Error" + ex) 86 | } 87 | 88 | }) 89 | 90 | //update degrees 91 | route.put("/:code", tf.verifyToken, (req, res) => { 92 | 93 | jwt.verify(req.token, config.secret, (err, authData) => { 94 | if (err) { 95 | res.status(403).json({ status: "forbidden" }) 96 | } else { 97 | try { 98 | const query = { dcode: req.params.code } 99 | Degrees.updateOne(query, req.body, (err) => { 100 | if (err) { 101 | console.log(err) 102 | res.status(500).json({ error: err }); 103 | } else { 104 | res.status(200).json({ status: true }) 105 | } 106 | }) 107 | } catch (ex) { 108 | res.status(500).send("Server Error" + ex) 109 | } 110 | } 111 | }) 112 | 113 | }) 114 | 115 | //delete degrees 116 | route.delete("/:code", tf.verifyToken, (req, res) => { 117 | 118 | jwt.verify(req.token, config.secret, (err, authData) => { 119 | if (err) { 120 | res.status(403).json({ status: "forbidden" }) 121 | } else { 122 | try { 123 | const query = { dcode: req.params.code } 124 | Degrees.deleteOne(query, (err) => { 125 | if (err) { 126 | console.log(err) 127 | res.status(500).json({ error: err }); 128 | } else { 129 | res.status(200).json({ status: true }) 130 | } 131 | }) 132 | } catch (ex) { 133 | res.status(500).send("Server Error" + ex) 134 | } 135 | } 136 | }) 137 | 138 | }) 139 | 140 | //get all courses of a degree 141 | //eg :- localhost:4000/degrees/SE/courses 142 | route.get("/:code/courses", tf.verifyToken, (req, res) => { 143 | 144 | jwt.verify(req.token, config.secret, (err, authData) => { 145 | if (err) { 146 | res.status(403).json({ status: "forbidden" }) 147 | } else { 148 | try { 149 | const query = { dcode: req.params.code } 150 | Courses.find(query, (err, course) => { 151 | if (err) { 152 | console.log(err); 153 | res.status(500).json({ error: err }); 154 | } else { 155 | res.status(200).json({ courses: course }) 156 | } 157 | }); 158 | } catch (ex) { 159 | res.status(500).send("Server Error" + ex) 160 | } 161 | } 162 | }) 163 | 164 | }) 165 | 166 | 167 | module.exports = route 168 | 169 | --------------------------------------------------------------------------------