diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml
index 03ed569..e2ac59c 100644
--- a/.github/workflows/linter.yml
+++ b/.github/workflows/linter.yml
@@ -16,7 +16,7 @@ name: Lint Code Base
#############################
on:
push:
- branches-ignore: [master, main]
+ branches-ignore: [master, main, back_development]
# Remove the line above to run when pushing to master
pull_request:
branches: [master, main]
@@ -35,6 +35,22 @@ jobs:
# Load all steps #
##################
steps:
+ - uses: actions/checkout@v3
+ - name: Set up JDK 17
+ uses: actions/setup-java@v3
+ with:
+ java-version: '17'
+ distribution: 'adopt'
+ - name: Build with Maven
+ run: |
+ cd src/backend/TimetableLinkAPI
+ mvn --batch-mode --update-snapshots package
+ - name: Run the Maven verify phase
+ run: |
+ #cd src/backend/TimetableLinkAPI
+ mvn --batch-mode --update-snapshots verify
+
+
##########################
# Checkout the code base #
##########################
diff --git a/.github/workflows/mvn.yml b/.github/workflows/mvn.yml
new file mode 100644
index 0000000..3af3d18
--- /dev/null
+++ b/.github/workflows/mvn.yml
@@ -0,0 +1,28 @@
+name: Java CI
+
+on:
+ push:
+ branches-ignore: [master, main, back_development]
+ # Remove the line above to run when pushing to master
+ pull_request:
+ branches: [master, main]
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v3
+ - name: Set up JDK 17
+ uses: actions/setup-java@v3
+ with:
+ java-version: '17'
+ distribution: 'adopt'
+ - name: Build with Maven
+ run: |
+ cd src/backend/TimetableLinkAPI
+ mvn --batch-mode --update-snapshots package
+ - name: Run the Maven verify phase
+ run: |
+ cd src/backend/TimetableLinkAPI
+ mvn --batch-mode --update-snapshots verify
diff --git a/.gitignore b/.gitignore
index b6e4761..b275ca6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -127,3 +127,6 @@ dmypy.json
# Pyre type checker
.pyre/
+
+#IntelliJ IDEA
+.idea
\ No newline at end of file
diff --git a/License.txt b/License.txt
new file mode 100644
index 0000000..953cb1d
--- /dev/null
+++ b/License.txt
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) [2022] [fullname]
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/README.md b/README.md
index 90aa2b9..5b23819 100644
--- a/README.md
+++ b/README.md
@@ -1,29 +1,46 @@
-# Brief Intro
+[](https://opensource.org/licenses/MIT)
-Project repo to link Moodle, MS Exchange, DoE updates and University Events in one centralized system.
+# Cross Link for University Innopolis schedules
+
+---
+
+This application is a combination of all `Innopolis University` timetables. With it, DoE will create events that will be sent to the calendars of students and teachers of the university. Moreover, this application combines all the events created on `Moodle and MS Exchange` and also sends them to the `Outlook calendars` of students and teachers.
+
+
+
+## Why this important?
+
+In `University Innopolis` there a lot of links that have some events on them(e.g. `Moodle, Outlook, MS Exchange`). So, our application unite all these timetables and send them to `Outlook Calendar`, because every participant of University Innopolis has Outlook account.
+
+## How to use?
+
+our application is based on the site, so just open the site and log in.
+[Event adder](https://degrassi-minister-88544.herokuapp.com/index.html)
+
+
+
+
+
+## Features
+
+There's some features in our application :
+1. `Adding events` to students' and teachers' calendars.
+2. `Edit and Delete` already created `events`
+3. `Import list of emails` from Outlook.
+4. `Create list of emails` on our site.
+5. `Edit and Delete` already created `mailing lists`.
+
+## Tools
+
+For frontend developing we used html, css and js. For backend developing of our site we used spring, docker, maven.
+
+
+
+
## Important Links
- [Usecase Diagram](https://drive.google.com/file/d/1nr23I5055SIXLq0PMvGGDPZAzz01xiW4/view?usp=sharing)
- [User Story](https://docs.google.com/spreadsheets/d/12BQN_QRp9IU6oKfjrk3xJsV7YisZib4y3s285RwqUo4/edit?usp=sharing)
- [Product Backlog](https://docs.google.com/document/d/1eF4ok6R33ai33qpmHXXPxxG4ZWCH8k8phtmZDnNVtxg/edit?usp=sharing)
-- [API Design](https://app.swaggerhub.com/apis/Timetable2/timetable/1.0.0)
- [Mock Server](https://www.postman.com/orange-astronaut-888988/workspace/timetable-api/collection/21222264-0d7b6da3-1e13-4bd9-af09-11720e694a00?ctx=documentation)
-
-## Developer Guide
-
-### Branching Rules
-- Keep branch names relevant to the sprint task (i.e. LoginFeature, EventFrontend)
-- Maintain separate branch for separate tasks
-
-### Commits
-- Commit message format - `[Commit Type] - [Brief]`
- Commit types
- - Patch
- - Feature
- - Minor Change
-- Keep commit to their respective branch (i.e. `Patch - Fixed frontend taskbar responsiveness` should not be commited to `LoginFeature` branch)
-
-## Pushing
-- Pushing to master is forbidden, branches would be merged later
-- To be accepted for a merge, code should either pass unittest (if applicable) or be checked for bugs by at least one other developer
\ No newline at end of file
diff --git a/images/CreateList.png b/images/CreateList.png
new file mode 100644
index 0000000..73e5e30
Binary files /dev/null and b/images/CreateList.png differ
diff --git a/images/EditEvent.png b/images/EditEvent.png
new file mode 100644
index 0000000..3241596
Binary files /dev/null and b/images/EditEvent.png differ
diff --git a/images/EditEvent2.png b/images/EditEvent2.png
new file mode 100644
index 0000000..40d50b3
Binary files /dev/null and b/images/EditEvent2.png differ
diff --git a/images/EditList.png b/images/EditList.png
new file mode 100644
index 0000000..a59f8c8
Binary files /dev/null and b/images/EditList.png differ
diff --git a/images/EditList2.png b/images/EditList2.png
new file mode 100644
index 0000000..5b4ece3
Binary files /dev/null and b/images/EditList2.png differ
diff --git a/src/backend/TimetableLinkAPI/.DS_Store b/src/backend/TimetableLinkAPI/.DS_Store
index 9a874b5..feca861 100644
Binary files a/src/backend/TimetableLinkAPI/.DS_Store and b/src/backend/TimetableLinkAPI/.DS_Store differ
diff --git a/src/backend/TimetableLinkAPI/Dockerfile b/src/backend/TimetableLinkAPI/Dockerfile
new file mode 100644
index 0000000..72ab994
--- /dev/null
+++ b/src/backend/TimetableLinkAPI/Dockerfile
@@ -0,0 +1,11 @@
+FROM maven as builder
+WORKDIR /usr/src/app
+COPY pom.xml .
+RUN mvn -B -e -C -T 1C org.apache.maven.plugins:maven-dependency-plugin:3.1.2:go-offline
+COPY . .
+RUN mvn package
+
+FROM openjdk:17
+EXPOSE 8080
+COPY --from=builder /usr/src/app/target/*.jar ./
+ENTRYPOINT ["java", "-jar", "/spring-boot-docker.jar"]
diff --git a/src/backend/TimetableLinkAPI/Procfile b/src/backend/TimetableLinkAPI/Procfile
new file mode 100644
index 0000000..678da31
--- /dev/null
+++ b/src/backend/TimetableLinkAPI/Procfile
@@ -0,0 +1 @@
+web: java $JAVA_OPTS -Dserver.port=$PORT -jar target/*.jar
\ No newline at end of file
diff --git a/src/backend/TimetableLinkAPI/docker-compose.yml b/src/backend/TimetableLinkAPI/docker-compose.yml
index b42f906..890d604 100644
--- a/src/backend/TimetableLinkAPI/docker-compose.yml
+++ b/src/backend/TimetableLinkAPI/docker-compose.yml
@@ -1,16 +1,32 @@
version: '3'
-
services:
+ server:
+ container_name: timetable_server
+ build: .
+ environment:
+ SPRING_APPLICATION_JSON: '{
+ "spring.datasource.url" : "jdbc:mysql://db:3306/timetable"
+ }'
+ ports:
+ - "8080:8080"
+ depends_on:
+ - db
+ restart: on-failure
+
+
db:
+ container_name: timetable_db
image: mysql:8.0
platform: linux/x86_64
restart: always
- command: --init-file /data/application/init.sql
- volumes:
- - ./init.sql:/data/application/init.sql
+# command: --init-file /data/application/schema.sql
+# volumes:
+# - ./schema.sql:/data/application/schema.sql
environment:
- MYSQL_DATABASE=timetable
- MYSQL_ROOT_PASSWORD=pass
ports:
- - '3306:3306'
+ - "3306:3306"
+
+
diff --git a/src/backend/TimetableLinkAPI/index.html b/src/backend/TimetableLinkAPI/index.html
deleted file mode 100644
index 0ebcfd4..0000000
--- a/src/backend/TimetableLinkAPI/index.html
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
- Title
-
-
-
-
-
\ No newline at end of file
diff --git a/src/backend/TimetableLinkAPI/pom.xml b/src/backend/TimetableLinkAPI/pom.xml
index eb25729..86b0605 100644
--- a/src/backend/TimetableLinkAPI/pom.xml
+++ b/src/backend/TimetableLinkAPI/pom.xml
@@ -53,24 +53,62 @@
5.3.20
-
+
- junit
- junit
- 4.13.2
+ org.junit.jupiter
+ junit-jupiter-api
+ 5.9.0-M1test
+
+ com.h2database
+ h2
+ test
+
-
+
+
+ org.assertj
+ assertj-core
+ 3.23.1
+ test
+
+
+
+ org.mockito
+ mockito-core
+ 4.6.1
+ test
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jdbc
+
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ runtime
+ true
+
+
+
+
+
+
+
+
org.springframework.bootspring-boot-maven-plugin
+ ${project.parent.version}
+ spring-boot-docker
-
diff --git a/src/backend/TimetableLinkAPI/src/main/.DS_Store b/src/backend/TimetableLinkAPI/src/main/.DS_Store
index 55c1fcb..5ddc54c 100644
Binary files a/src/backend/TimetableLinkAPI/src/main/.DS_Store and b/src/backend/TimetableLinkAPI/src/main/.DS_Store differ
diff --git a/src/backend/TimetableLinkAPI/src/main/java/com/timetable/App.java b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/App.java
index 9558d10..eb3d28d 100644
--- a/src/backend/TimetableLinkAPI/src/main/java/com/timetable/App.java
+++ b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/App.java
@@ -1,6 +1,9 @@
package com.timetable;
//import com.timetable.jdbc.SpringJdbcConfig;
+import com.timetable.authentication.AuthenticationConfig;
+import com.timetable.authentication.AuthenticationRepository;
+import com.timetable.authentication.RequestAuthenticationCheck;
import com.timetable.jdbc.SpringJdbcConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
@@ -11,31 +14,25 @@
import org.springframework.context.annotation.PropertySource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
-import org.springframework.web.servlet.config.annotation.*;
-
-import javax.sql.DataSource;
+import org.springframework.web.context.request.WebRequestInterceptor;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.config.annotation.EnableWebMvc;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@SpringBootApplication
-@Import({SpringJdbcConfig.class})
-//@EnableWebMvc
-public class App {
+@Import({SpringJdbcConfig.class, AuthenticationConfig.class})
+public class App extends WebMvcConfigurerAdapter {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
-// @Override
-// public void addViewControllers(ViewControllerRegistry registry) {
-// registry.addViewController("/").setViewName("forward:/index.html");
-// }
-//
-// @Bean
-// public WebMvcConfigurer corsConfigurer() {
-// return new WebMvcConfigurerAdapter() {
-// @Override
-// public void addCorsMappings(CorsRegistry registry) {
-// registry.addMapping("/**")
-// .allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH");
-// }
-// };
-// }
+ @Autowired
+ private RequestAuthenticationCheck authenticationInterceptor;
+
+
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ registry.addInterceptor(authenticationInterceptor);
+ }
}
diff --git a/src/backend/TimetableLinkAPI/src/main/java/com/timetable/authentication/AuthenticationConfig.java b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/authentication/AuthenticationConfig.java
new file mode 100644
index 0000000..ab3783f
--- /dev/null
+++ b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/authentication/AuthenticationConfig.java
@@ -0,0 +1,29 @@
+package com.timetable.authentication;
+
+import com.timetable.jdbc.SpringJdbcConfig;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.SpringApplication;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
+
+@Configuration
+@ComponentScan
+public class AuthenticationConfig extends WebMvcConfigurerAdapter {
+
+ private final RequestAuthenticationCheck authenticationInterceptor;
+
+ @Autowired
+ public AuthenticationConfig(RequestAuthenticationCheck authenticationInterceptor) {
+ this.authenticationInterceptor = authenticationInterceptor;
+ }
+
+
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ registry.addInterceptor(authenticationInterceptor);
+ }
+}
diff --git a/src/backend/TimetableLinkAPI/src/main/java/com/timetable/authentication/AuthenticationController.java b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/authentication/AuthenticationController.java
new file mode 100644
index 0000000..81d1676
--- /dev/null
+++ b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/authentication/AuthenticationController.java
@@ -0,0 +1,35 @@
+package com.timetable.authentication;
+
+import com.timetable.outlook.OutlookConnector;
+import com.timetable.user.User;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.server.ResponseStatusException;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@RestController
+public class AuthenticationController {
+ AuthenticationService authenticationService;
+
+ @Autowired
+ AuthenticationController(AuthenticationService authenticationService) {
+ this.authenticationService = authenticationService;
+ }
+
+ @PostMapping("/login")
+ public Map login(@RequestBody User user) {
+ try {
+ authenticationService.login(user.getEmail(), user.getPassword());
+ String token = authenticationService.generateNewToken();
+ Map tokenJson = new HashMap<>();
+ tokenJson.put("token", token);
+ return tokenJson;
+ } catch (Exception ex) {
+ throw new ResponseStatusException(HttpStatus.FORBIDDEN);
+ }
+ }
+}
diff --git a/src/backend/TimetableLinkAPI/src/main/java/com/timetable/authentication/AuthenticationMySQLRepository.java b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/authentication/AuthenticationMySQLRepository.java
new file mode 100644
index 0000000..10ae3ca
--- /dev/null
+++ b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/authentication/AuthenticationMySQLRepository.java
@@ -0,0 +1,35 @@
+package com.timetable.authentication;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public class AuthenticationMySQLRepository implements AuthenticationRepository {
+ private final JdbcTemplate jdbcTemplate;
+
+ @Autowired
+ public AuthenticationMySQLRepository(JdbcTemplate jdbcTemplate) {
+ this.jdbcTemplate = jdbcTemplate;
+ }
+
+ @Override
+ public void saveToken(String token, Long expireTime) {
+ jdbcTemplate.update(
+ "INSERT INTO token (content, expireTime) values (?, ?)",
+ token, expireTime);
+ }
+
+ @Override
+ public void renewTokens(Long currentTime) {
+ jdbcTemplate.update(
+ "DELETE FROM token WHERE expireTime < ?", currentTime);
+ }
+
+ @Override
+ public boolean tokenExists(String token) {
+ Long exists = jdbcTemplate.queryForObject(
+ "SELECT COUNT(*) FROM token WHERE content = ?", Long.class, token);
+ return exists != null && exists.compareTo(0L) > 0;
+ }
+}
diff --git a/src/backend/TimetableLinkAPI/src/main/java/com/timetable/authentication/AuthenticationRepository.java b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/authentication/AuthenticationRepository.java
new file mode 100644
index 0000000..7b28f3a
--- /dev/null
+++ b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/authentication/AuthenticationRepository.java
@@ -0,0 +1,7 @@
+package com.timetable.authentication;
+
+public interface AuthenticationRepository {
+ void saveToken(String token, Long expireTime);
+ void renewTokens(Long currentTime);
+ boolean tokenExists(String token);
+}
diff --git a/src/backend/TimetableLinkAPI/src/main/java/com/timetable/authentication/AuthenticationService.java b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/authentication/AuthenticationService.java
new file mode 100644
index 0000000..14f2818
--- /dev/null
+++ b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/authentication/AuthenticationService.java
@@ -0,0 +1,48 @@
+package com.timetable.authentication;
+
+import com.timetable.outlook.OutlookConnector;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.stereotype.Service;
+
+import java.security.SecureRandom;
+import java.util.Base64;
+
+@Service
+@PropertySource("classpath:security.properties")
+public class AuthenticationService {
+ private final SecureRandom secureRandom = new SecureRandom();
+ private final Base64.Encoder base64Encoder = Base64.getUrlEncoder();
+ private final OutlookConnector outlookConnector;
+ private final AuthenticationRepository authenticationRepository;
+ private final Long tokenLifetime;
+
+ @Autowired
+ AuthenticationService(OutlookConnector outlookConnector,
+ AuthenticationRepository authenticationRepository,
+ @Value("${token.lifetime}") Long tokenLifetime) {
+ this.outlookConnector = outlookConnector;
+ this.authenticationRepository = authenticationRepository;
+ this.tokenLifetime = tokenLifetime;
+ }
+
+ public void login(String email, String password) throws Exception {
+ outlookConnector.setCredentials(email, password);
+ }
+
+ public String generateNewToken() {
+ byte[] randomBytes = new byte[24];
+ secureRandom.nextBytes(randomBytes);
+ String token = base64Encoder.encodeToString(randomBytes);
+ Long currentTime = System.currentTimeMillis();
+ authenticationRepository.saveToken(token, currentTime + tokenLifetime);
+ return token;
+ }
+
+ public boolean checkToken(String token) {
+ Long currentTime = System.currentTimeMillis();
+ authenticationRepository.renewTokens(currentTime);
+ return authenticationRepository.tokenExists(token);
+ }
+}
diff --git a/src/backend/TimetableLinkAPI/src/main/java/com/timetable/authentication/RequestAuthenticationCheck.java b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/authentication/RequestAuthenticationCheck.java
new file mode 100644
index 0000000..14057c3
--- /dev/null
+++ b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/authentication/RequestAuthenticationCheck.java
@@ -0,0 +1,39 @@
+package com.timetable.authentication;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Component;
+import org.springframework.web.client.HttpStatusCodeException;
+import org.springframework.web.server.ResponseStatusException;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@Component
+public class RequestAuthenticationCheck implements HandlerInterceptor {
+ private final AuthenticationService authenticationService;
+
+ @Autowired
+ public RequestAuthenticationCheck(AuthenticationService authenticationService) {
+ this.authenticationService = authenticationService;
+ }
+
+ @Override
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+ //System.out.println(request.getServletPath());
+ if (request.getServletPath().equals("/") ||
+ request.getServletPath().equals("/login") ||
+ request.getServletPath().endsWith(".html") ||
+ request.getServletPath().endsWith(".js") ||
+ request.getServletPath().endsWith(".css") ||
+ request.getServletPath().endsWith(".ico"))
+ return true;
+ System.out.println("catch");
+ String token = request.getHeader("Authorization");
+ if (authenticationService.checkToken(token))
+ return true;
+ else throw new ResponseStatusException(HttpStatus.FORBIDDEN);
+ }
+}
diff --git a/src/backend/TimetableLinkAPI/src/main/java/com/timetable/event/EventController.java b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/event/EventController.java
index e3b9da3..6fdb747 100644
--- a/src/backend/TimetableLinkAPI/src/main/java/com/timetable/event/EventController.java
+++ b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/event/EventController.java
@@ -2,15 +2,14 @@
import org.apache.tomcat.util.buf.UDecoder;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.util.UriUtils;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
-import java.util.Base64;
-import java.util.Date;
-import java.util.List;
+import java.util.*;
@RestController
@RequestMapping(path = "/events")
@@ -23,17 +22,16 @@ public EventController(EventService eventService) {
}
@PostMapping
- @CrossOrigin(origins = "http://localhost:63342")
- public String createEvent(@RequestBody Event event) {
- //System.out.println(event.getEndDate());
- String eventId = null;
+ public Map createEvent(@RequestBody Event event) {
+ Map eventIdMap = new HashMap<>();
try {
- eventId = eventService.createEvent(event);
+ String eventId = eventService.createEvent(event);
+ eventIdMap.put("eventId", eventId);
}
catch (Exception ex) {
ex.printStackTrace();
}
- return eventId;
+ return eventIdMap;
}
@GetMapping ("/{eventId}")
@@ -100,6 +98,15 @@ public List getAllEvents() {
return events;
}
+ @GetMapping("/names")
+ public List getAllNames() {
+ List names = null;
+ try {
+ names = getAllEvents().stream().map(Event::getName).toList();
+ } catch (Exception ex) {}
+ return names;
+ }
+
@PatchMapping ("/{eventId}/invite/{mailingListTextIdentifier}")
public void inviteAllFromMailingList(@PathVariable String eventId,
@PathVariable String mailingListTextIdentifier) {
diff --git a/src/backend/TimetableLinkAPI/src/main/java/com/timetable/event/EventService.java b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/event/EventService.java
index 227f068..a775cb6 100644
--- a/src/backend/TimetableLinkAPI/src/main/java/com/timetable/event/EventService.java
+++ b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/event/EventService.java
@@ -31,7 +31,9 @@ public List getAllEvents() throws Exception {
List eventIds = eventRepository.getAllIds();
List events = new ArrayList<>();
for (String id : eventIds) {
- events.add(getEvent(id));
+ try {
+ events.add(getEvent(id));
+ } catch(Exception ignored) {}
}
return events;
}
@@ -39,9 +41,11 @@ public List getAllEvents() throws Exception {
public List getEventsFromTimeInterval(Date start, Date end) throws Exception {
List filteredEvents = new ArrayList<>();
for (Event event : getAllEvents()) {
- if (event.getStartDate().after(start) && event.getEndDate().before(end)) {
- filteredEvents.add(event);
- }
+ try {
+ if (event.getStartDate().after(start) && event.getEndDate().before(end)) {
+ filteredEvents.add(event);
+ }
+ } catch (Exception ignored) {}
}
return filteredEvents;
}
diff --git a/src/backend/TimetableLinkAPI/src/main/java/com/timetable/event/OutlookEventManager.java b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/event/OutlookEventManager.java
index 0b7cae7..22f3a68 100644
--- a/src/backend/TimetableLinkAPI/src/main/java/com/timetable/event/OutlookEventManager.java
+++ b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/event/OutlookEventManager.java
@@ -13,6 +13,7 @@
import microsoft.exchange.webservices.data.search.FindItemsResults;
import microsoft.exchange.webservices.data.search.ItemView;
import microsoft.exchange.webservices.data.search.filter.SearchFilter;
+import microsoft.exchange.webservices.data.core.enumeration.service.ConflictResolutionMode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -83,7 +84,7 @@ public void updateEvent(String encodedId, Event event) throws Exception {
appointment.setStart(event.getStartDate());
appointment.setEnd(event.getEndDate());
appointment.setLocation(event.getLocation());
- appointment.save();
+ appointment.update(ConflictResolutionMode.AutoResolve);
}
public void cancelEvent(String eventId) throws Exception {
diff --git a/src/backend/TimetableLinkAPI/src/main/java/com/timetable/jdbc/SpringJdbcConfig.java b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/jdbc/SpringJdbcConfig.java
index c6e37d6..6c0fec0 100644
--- a/src/backend/TimetableLinkAPI/src/main/java/com/timetable/jdbc/SpringJdbcConfig.java
+++ b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/jdbc/SpringJdbcConfig.java
@@ -7,6 +7,7 @@
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.PropertySource;
import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.SqlOutParameter;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import javax.sql.DataSource;
@@ -15,7 +16,6 @@
@PropertySource("classpath:application.properties")
public class SpringJdbcConfig {
@Bean
- //@Primary
public DataSource mySqlDataSource(
@Value("${spring.datasource.username}") String username,
@Value("${spring.datasource.url}") String url,
@@ -27,7 +27,10 @@ public DataSource mySqlDataSource(
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
-
+// System.out.println("username " + username);
+// System.out.println("url " + url);
+// System.out.println("password " + password);
+// System.out.println("driver " + driverClassName);
return dataSource;
}
diff --git a/src/backend/TimetableLinkAPI/src/main/java/com/timetable/mailing_list/MailingList.java b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/mailing_list/MailingList.java
index 0a3e4da..ceaa05c 100644
--- a/src/backend/TimetableLinkAPI/src/main/java/com/timetable/mailing_list/MailingList.java
+++ b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/mailing_list/MailingList.java
@@ -3,7 +3,9 @@
import microsoft.exchange.webservices.data.property.complex.EmailAddress;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
+import java.util.Objects;
public class MailingList {
private final String textIdentifier;
@@ -23,19 +25,17 @@ public List getEmails() {
}
-// public List getEmails() {
-// return emails;
-// }
-//
-// public void setEmails(List emails) {
-// this.emails = emails;
-// }
-//
-// public void addEvent(EmailAddress email) {
-// emails.add(email);
-// }
-//
-// public void excludeEmail(EmailAddress email) {
-// emails.remove(email);
-// }
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ MailingList that = (MailingList) o;
+ return textIdentifier.equals(that.textIdentifier)
+ && (new HashSet<>(emails)).equals(new HashSet<>(that.emails));
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(textIdentifier, new HashSet<>(emails));
+ }
}
diff --git a/src/backend/TimetableLinkAPI/src/main/java/com/timetable/mailing_list/MailingListController.java b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/mailing_list/MailingListController.java
index 004a238..33a3c84 100644
--- a/src/backend/TimetableLinkAPI/src/main/java/com/timetable/mailing_list/MailingListController.java
+++ b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/mailing_list/MailingListController.java
@@ -2,6 +2,7 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
+
import java.util.List;
@RestController
@@ -36,6 +37,20 @@ public void deleteEmailsFromList(@PathVariable String textIdentifier,
mailingListService.deleteEmailsFromList(textIdentifier, emails);
}
+ @PatchMapping("/{textIdentifier}/emails/update")
+ public void updateEmailsFromList(@PathVariable String textIdentifier,
+ @RequestBody List emails) {
+ mailingListService.updateEmailsFromList(textIdentifier, emails);
+ }
+
+ @PatchMapping("/{textIdentifier}")
+ public void updateTextIdentifier(
+ @PathVariable String textIdentifier,
+ @RequestParam String newTextIdentifier) {
+ mailingListService.updateTextIdentifier(textIdentifier, newTextIdentifier);
+ }
+
+
@GetMapping("/{textIdentifier}/emails")
public List getEmailsFormList(@PathVariable String textIdentifier) {
return mailingListService.getEmailsFromList(textIdentifier);
diff --git a/src/backend/TimetableLinkAPI/src/main/java/com/timetable/mailing_list/MailingListManager.java b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/mailing_list/MailingListManager.java
new file mode 100644
index 0000000..a54cc09
--- /dev/null
+++ b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/mailing_list/MailingListManager.java
@@ -0,0 +1,8 @@
+package com.timetable.mailing_list;
+
+import java.util.List;
+
+public interface MailingListManager {
+ List importMailingLists() throws Exception;
+ void cancelInvitations(String eventId, List emails) throws Exception;
+}
diff --git a/src/backend/TimetableLinkAPI/src/main/java/com/timetable/mailing_list/MailingListMySQLRepository.java b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/mailing_list/MailingListMySQLRepository.java
index 02f86cd..03a7b13 100644
--- a/src/backend/TimetableLinkAPI/src/main/java/com/timetable/mailing_list/MailingListMySQLRepository.java
+++ b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/mailing_list/MailingListMySQLRepository.java
@@ -1,8 +1,11 @@
package com.timetable.mailing_list;
+import microsoft.exchange.webservices.data.core.service.item.Appointment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.SqlOutParameter;
+import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.stereotype.Repository;
import java.util.ArrayList;
@@ -19,7 +22,6 @@ public MailingListMySQLRepository(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
-
@Override
public List getMailingListsNames() {
return jdbcTemplate.queryForList(
@@ -104,12 +106,16 @@ public void deleteEmailFromList(Long mailingListId, String emailAddress) {
Long emailId = jdbcTemplate.queryForObject(
"""
SELECT email.id FROM email
- JOIN emailBelonging ON email.id = emailBelonging.emailId
- WHERE email.emailAddress = ?;
+ JOIN emailBelonging ON email.id = emailBelonging.emailId
+ WHERE email.emailAddress = ?
+ LIMIT 1;
""", Long.class, emailAddress);
jdbcTemplate.update(
"DELETE FROM emailBelonging WHERE mailingListId = ? AND emailId = ?",
mailingListId, emailId);
+// List list = jdbcTemplate.queryForList(
+// "SELECT id FROM emailBelonging", String.class
+// );
jdbcTemplate.update(
"""
DELETE FROM email
@@ -138,19 +144,63 @@ public void updateMailingList(MailingList mailingList) {
emailsToAdd.forEach(email -> addEmailToList(id, email));
}
+ @Override
+ public void updateTextIdentifier(String textIdentifier, String newTextIdentifier) {
+ jdbcTemplate.update(
+ """
+ UPDATE mailingList
+ SET textIdentifier = ?
+ WHERE textIdentifier = ?;
+ """, newTextIdentifier, textIdentifier);
+ }
+
- private List getEmailsByListId(Long mailingListId) {
+ @Override
+ public List getEmailsByListId(Long mailingListId) {
String getEmailsSqlRequest =
"""
SELECT DISTINCT emailAddress FROM
email LEFT JOIN emailBelonging
ON email.id = emailBelonging.emailId
- WHERE mailingListId = ?
+ WHERE mailingListId = ?;
""";
return jdbcTemplate.queryForList(
getEmailsSqlRequest, String.class, mailingListId);
}
+ public void init() {
+ jdbcTemplate.update(
+ """
+ CREATE DATABASE IF NOT EXISTS timetable;
+ USE timetable;
+
+ SET SQL_SAFE_UPDATES = 0;
+
+ CREATE TABLE IF NOT EXISTS mailingList (
+ id BIGINT PRIMARY KEY AUTO_INCREMENT,
+ textIdentifier VARCHAR(40) UNIQUE
+ );
+
+ CREATE TABLE IF NOT EXISTS email(
+ id BIGINT PRIMARY KEY AUTO_INCREMENT,
+ emailAddress VARCHAR(60) UNIQUE
+ );
+
+ CREATE TABLE IF NOT EXISTS emailBelonging(
+ id BIGINT PRIMARY KEY AUTO_INCREMENT,
+ emailId BIGINT,
+ mailingListId BIGINT,
+ FOREIGN KEY (emailId) REFERENCES email (id) ON DELETE CASCADE,
+ FOREIGN KEY (mailingListId) references mailingList (id) ON DELETE CASCADE
+ );
+
+ CREATE TABLE IF NOT EXISTS event(
+ outlookAppointmentId varchar(400) PRIMARY KEY
+ );
+ """
+ );
+ }
+
private String getTextIdentifier(Long mailingListId) {
String getMailingListTextIdentifierSql =
"SELECT textIdentifier FROM mailingList WHERE id = ?";
diff --git a/src/backend/TimetableLinkAPI/src/main/java/com/timetable/mailing_list/MailingListRepository.java b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/mailing_list/MailingListRepository.java
index defb31a..91e6d21 100644
--- a/src/backend/TimetableLinkAPI/src/main/java/com/timetable/mailing_list/MailingListRepository.java
+++ b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/mailing_list/MailingListRepository.java
@@ -16,4 +16,7 @@ public interface MailingListRepository {
void deleteEmailFromList(Long mailingListId, String emailAddress);
boolean mailingListExists(String textIdentifier);
void updateMailingList(MailingList mailingList);
+ void updateTextIdentifier(String textIdentifier, String newTextIdentifier);
+ List getEmailsByListId(Long id);
+ void init();
}
diff --git a/src/backend/TimetableLinkAPI/src/main/java/com/timetable/mailing_list/MailingListService.java b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/mailing_list/MailingListService.java
index 37005d7..7bd58c5 100644
--- a/src/backend/TimetableLinkAPI/src/main/java/com/timetable/mailing_list/MailingListService.java
+++ b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/mailing_list/MailingListService.java
@@ -2,7 +2,10 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
+
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
@Service
public class MailingListService {
@@ -36,14 +39,29 @@ public void deleteMailingList(String textIdentifier) {
public void addEmailsToList(String textIdentifier, List emails) {
Long mailingListId = mailingListRepository.getMailingListId(textIdentifier);
- emails.forEach(emailAddress ->
- mailingListRepository.addEmailToList(mailingListId, emailAddress));
+ emails.forEach(emailAddress -> {
+ System.out.println("1");
+ mailingListRepository.addEmailToList(mailingListId, emailAddress);
+ });
}
public void deleteEmailsFromList(String textIdentifier, List emails) {
Long mailingListId = mailingListRepository.getMailingListId(textIdentifier);
- emails.forEach(emailAddress ->
- mailingListRepository.deleteEmailFromList(mailingListId, emailAddress));
+ for (String emailAddress : emails) {
+ try {
+ System.out.println("2");
+ //System.out.println("before " + getEmailsFromList(textIdentifier).toString());
+ mailingListRepository.deleteEmailFromList(mailingListId, emailAddress);
+ //System.out.println("after " + getEmailsFromList(textIdentifier).toString());
+ } catch(Exception ex){
+ ex.printStackTrace();
+ }
+ }
+ }
+
+ public void updateEmailsFromList(String textIdentifier, List emails) {
+ MailingList updatedMailingList = new MailingList(textIdentifier, emails);
+ updateExistingMailingList(updatedMailingList);
}
public MailingList getMailingList(String textIdentifier) {
@@ -65,7 +83,7 @@ public void importMailingList() throws Exception {
mailingLists.forEach(mailingList -> {
// Long id = mailingListRepository.getMailingListId(mailingList.getTextIdentifier());
if (mailingListRepository.mailingListExists(mailingList.getTextIdentifier())) {
- mailingListRepository.updateMailingList(mailingList);
+ updateExistingMailingList(mailingList);
} else {
mailingListRepository.createMailingList(mailingList);
}
@@ -76,4 +94,22 @@ public void cancelInvitations(String eventId, String textIdentifier) throws Exce
List emails = getEmailsFromList(textIdentifier);
mailingListManager.cancelInvitations(eventId, emails);
}
+
+ public void updateTextIdentifier(String textIdentifier, String newTextIdentifier) {
+ mailingListRepository.updateTextIdentifier(textIdentifier, newTextIdentifier);
+ }
+
+ private void updateExistingMailingList(MailingList mailingList) {
+ Long id = mailingListRepository.getMailingListId(mailingList.getTextIdentifier());
+ Set oldEmails = new HashSet<>(mailingListRepository.getEmailsByListId(id));
+ Set newEmails = new HashSet<>(mailingList.getEmails());
+ Set emailsToDelete = new HashSet<>(oldEmails);
+ emailsToDelete.removeAll(newEmails);
+ Set emailsToAdd = new HashSet<>(newEmails);
+ emailsToAdd.removeAll(oldEmails);
+ emailsToDelete.forEach(email ->
+ mailingListRepository.deleteEmailFromList(id, email));
+ emailsToAdd.forEach(email ->
+ mailingListRepository.addEmailToList(id, email));
+ }
}
diff --git a/src/backend/TimetableLinkAPI/src/main/java/com/timetable/mailing_list/OutlookMailingListManager.java b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/mailing_list/OutlookMailingListManager.java
index 5da2fee..95de6a8 100644
--- a/src/backend/TimetableLinkAPI/src/main/java/com/timetable/mailing_list/OutlookMailingListManager.java
+++ b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/mailing_list/OutlookMailingListManager.java
@@ -27,7 +27,7 @@
import java.util.List;
@Component
-public class OutlookMailingListManager {
+public class OutlookMailingListManager implements MailingListManager {
private final ExchangeService service;
private final OutlookEventManager eventManager;
@@ -69,7 +69,7 @@ public void cancelInvitations(String eventId, List emails) throws Except
appointment.update(ConflictResolutionMode.AlwaysOverwrite, SendInvitationsOrCancellationsMode.SendToNone);
}
- public void filterInvitations(AttendeeCollection attendees, List emails) {
+ private void filterInvitations(AttendeeCollection attendees, List emails) {
for (int i = 0; i <= attendees.getCount(); i++) {
Attendee attendee = attendees.getPropertyAtIndex(i);
if (emails.contains(attendee.getAddress())) {
diff --git a/src/backend/TimetableLinkAPI/src/main/java/com/timetable/outlook/OutlookConnector.java b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/outlook/OutlookConnector.java
index 26c7e74..ee12f96 100644
--- a/src/backend/TimetableLinkAPI/src/main/java/com/timetable/outlook/OutlookConnector.java
+++ b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/outlook/OutlookConnector.java
@@ -10,26 +10,36 @@
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
+import java.net.URI;
+
@Component
@PropertySource("classpath:personal.properties")
public class OutlookConnector {
private ExchangeService service;
- private ExchangeCredentials credentials;
+ //private ExchangeCredentials credentials;
@Autowired
public OutlookConnector(
@Value("${personal.email}") String personalEmail,
@Value("${personal.password}") String personalPassword) {
- service = new ExchangeService(ExchangeVersion.Exchange2010_SP2);
+ service = new ExchangeService(ExchangeVersion.Exchange2010_SP2);
+// service = new ExchangeService(ExchangeVersion.Exchange2010_SP2);
+// ExchangeCredentials credentials = new WebCredentials(personalEmail, personalPassword);
+// service.setCredentials(credentials);
+// try {
+// service.autodiscoverUrl(
+// personalEmail, new OutlookConnector.RedirectionUrlCallback());
+// } catch (Exception e) {
+// e.printStackTrace();
+// }
+
+ }
+
+ public void setCredentials(String personalEmail, String personalPassword) throws Exception {
ExchangeCredentials credentials = new WebCredentials(personalEmail, personalPassword);
service.setCredentials(credentials);
- try {
- service.autodiscoverUrl(
- personalEmail, new OutlookConnector.RedirectionUrlCallback());
- } catch (Exception e) {
- e.printStackTrace();
- }
-
+ service.autodiscoverUrl(
+ personalEmail, new OutlookConnector.RedirectionUrlCallback());
}
public ExchangeService getService() {
diff --git a/src/backend/TimetableLinkAPI/src/main/java/com/timetable/user/User.java b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/user/User.java
new file mode 100644
index 0000000..01e205b
--- /dev/null
+++ b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/user/User.java
@@ -0,0 +1,15 @@
+package com.timetable.user;
+
+public class User {
+ private String email;
+ private String password;
+
+
+ public String getEmail() {
+ return email;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+}
diff --git a/src/backend/TimetableLinkAPI/src/main/java/com/timetable/view/ViewController.java b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/view/ViewController.java
new file mode 100644
index 0000000..370db37
--- /dev/null
+++ b/src/backend/TimetableLinkAPI/src/main/java/com/timetable/view/ViewController.java
@@ -0,0 +1,19 @@
+package com.timetable.view;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+
+@Controller
+public class ViewController {
+ @GetMapping("")
+ public String login() {
+ return "login.html";
+ }
+
+ @GetMapping("/create/mailing")
+ public String create_mailing(){ return "post_mailing_list.html";}
+
+ @GetMapping("/edit/mailing")
+ public String edit_mailing(){ return "edit_mailing_list.html";}
+}
+
diff --git a/src/backend/TimetableLinkAPI/src/main/resources/.DS_Store b/src/backend/TimetableLinkAPI/src/main/resources/.DS_Store
new file mode 100644
index 0000000..2a43b86
Binary files /dev/null and b/src/backend/TimetableLinkAPI/src/main/resources/.DS_Store differ
diff --git a/src/backend/TimetableLinkAPI/src/main/resources/application.properties b/src/backend/TimetableLinkAPI/src/main/resources/application.properties
index 7359aad..c3c5bfd 100644
--- a/src/backend/TimetableLinkAPI/src/main/resources/application.properties
+++ b/src/backend/TimetableLinkAPI/src/main/resources/application.properties
@@ -1,4 +1,6 @@
spring.datasource.username=root
spring.datasource.url=jdbc:mysql://localhost:3306/timetable
spring.datasource.password=pass
-spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
\ No newline at end of file
+spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
+spring.sql.init.mode=always
+server.port=${PORT:8080}
\ No newline at end of file
diff --git a/src/backend/TimetableLinkAPI/src/main/resources/schema.sql b/src/backend/TimetableLinkAPI/src/main/resources/schema.sql
new file mode 100644
index 0000000..4dda7e8
--- /dev/null
+++ b/src/backend/TimetableLinkAPI/src/main/resources/schema.sql
@@ -0,0 +1,39 @@
+CREATE DATABASE IF NOT EXISTS timetable;
+USE timetable;
+
+SET SQL_SAFE_UPDATES = 0;
+
+CREATE TABLE IF NOT EXISTS mailingList (
+ id BIGINT PRIMARY KEY AUTO_INCREMENT,
+ textIdentifier VARCHAR(40) UNIQUE
+);
+
+CREATE TABLE IF NOT EXISTS email(
+ id BIGINT PRIMARY KEY AUTO_INCREMENT,
+ emailAddress VARCHAR(60) UNIQUE
+);
+
+CREATE TABLE IF NOT EXISTS emailBelonging(
+ id BIGINT PRIMARY KEY AUTO_INCREMENT,
+ emailId BIGINT,
+ mailingListId BIGINT,
+ FOREIGN KEY (emailId) REFERENCES email (id) ON DELETE CASCADE,
+ FOREIGN KEY (mailingListId) references mailingList (id) ON DELETE CASCADE
+);
+
+CREATE TABLE IF NOT EXISTS event(
+ outlookAppointmentId VARCHAR(400) PRIMARY KEY
+);
+
+CREATE TABLE IF NOT EXISTS token(
+ content VARCHAR(100),
+ expireTime BIGINT
+);
+
+-- CREATE DATABASE IF NOT EXISTS test;
+-- USE test;
+--
+-- CREATE TABLE LIKE timetable.mailingList;
+-- CREATE TABLE LIKE timetable.email;
+-- CREATE TABLE LIKE timetable.emailBelonging;
+-- CREATE TABLE LIKE timetable.event;
\ No newline at end of file
diff --git a/src/backend/TimetableLinkAPI/src/main/resources/security.properties b/src/backend/TimetableLinkAPI/src/main/resources/security.properties
new file mode 100644
index 0000000..1affa37
--- /dev/null
+++ b/src/backend/TimetableLinkAPI/src/main/resources/security.properties
@@ -0,0 +1 @@
+token.lifetime=3600000
\ No newline at end of file
diff --git a/src/backend/TimetableLinkAPI/src/main/resources/static/authorise.js b/src/backend/TimetableLinkAPI/src/main/resources/static/authorise.js
new file mode 100644
index 0000000..4be1bff
--- /dev/null
+++ b/src/backend/TimetableLinkAPI/src/main/resources/static/authorise.js
@@ -0,0 +1,39 @@
+let loginBtn = document.getElementById('login-btn')
+
+loginBtn.addEventListener('click', (event) => {
+ event.preventDefault()
+
+ fetch('/login', {
+
+ method: 'POST',
+ body: JSON.stringify({
+ email: document.getElementById('username').value,
+ password: document.getElementById('password').value
+ }),
+ headers: {
+ 'Content-Type': 'application/json'
+ }
+ })
+ .then(response => {
+ console.log(response);
+ if (response.status === 403) {
+ processWrongData();
+ return;
+ }
+ return response.json();
+ })
+ .then(data => {
+ console.log(data)
+ loginBtn.setAttribute('disabled', 'true')
+ let currentToken = data["token"];
+ sessionStorage.setItem("token", currentToken);
+ window.location.replace("index.html");
+ })
+ .catch(error => console.log(error))
+})
+
+function processWrongData() {
+ alert('Wrong data. Make sure you use Innopolis account. Try again...');
+ document.getElementById('username').value = '';
+ document.getElementById('password').value = '';
+}
diff --git a/src/frontend/static/bootstrap.css b/src/backend/TimetableLinkAPI/src/main/resources/static/bootstrap.css
similarity index 100%
rename from src/frontend/static/bootstrap.css
rename to src/backend/TimetableLinkAPI/src/main/resources/static/bootstrap.css
diff --git a/src/frontend/static/bootstrap.js b/src/backend/TimetableLinkAPI/src/main/resources/static/bootstrap.js
similarity index 100%
rename from src/frontend/static/bootstrap.js
rename to src/backend/TimetableLinkAPI/src/main/resources/static/bootstrap.js
diff --git a/src/frontend/static/dayjs.js b/src/backend/TimetableLinkAPI/src/main/resources/static/dayjs.js
similarity index 100%
rename from src/frontend/static/dayjs.js
rename to src/backend/TimetableLinkAPI/src/main/resources/static/dayjs.js
diff --git a/src/backend/TimetableLinkAPI/src/main/resources/static/edit_event.html b/src/backend/TimetableLinkAPI/src/main/resources/static/edit_event.html
new file mode 100644
index 0000000..3c0b424
--- /dev/null
+++ b/src/backend/TimetableLinkAPI/src/main/resources/static/edit_event.html
@@ -0,0 +1,110 @@
+
+
+
+
+ Edit event
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Get events from the time interval
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Set new name for event
+
+
+
+
+
+
+
Set new location
+
+
+
+
+
+
+
Edit dates
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Interaction with mailing lists
+
+
+
Send invitations to chosen event to all people from a chosen mail list
+
+
+
Cancel invitations to chosen event to all people from a chosen mail list