Index: springapp/src/main/java/mk/profesori/springapp/Controller/PublicController.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Controller/PublicController.java	(revision 8d831804abcee99d72c207c57a8f16e54b1329a2)
+++ springapp/src/main/java/mk/profesori/springapp/Controller/PublicController.java	(revision c68150fac8ab8e6f5dc5b8b2a9cd73d391dc1aa7)
@@ -18,10 +18,12 @@
 import mk.profesori.springapp.Model.Professor;
 import mk.profesori.springapp.Model.StudyProgramme;
+import mk.profesori.springapp.Model.Subject;
 import mk.profesori.springapp.Model.University;
+import mk.profesori.springapp.Model._Thread;
 import mk.profesori.springapp.Service.MainService;
 
 @RestController
 @RequestMapping("/public")
-@CrossOrigin(origins = { "http://192.168.0.17:3000", "http://192.168.0.28:3000" })
+@CrossOrigin(origins = { "http://192.168.0.17:3000", "http://192.168.0.39:3000" })
 public class PublicController {
 
@@ -98,4 +100,14 @@
     }
 
+    @RequestMapping(value = "/subject/{subjectId}", method = RequestMethod.GET)
+    public Subject getSubjectById(@PathVariable Long subjectId) {
+        return mainService.getSubjectById(subjectId); // vrakja predmet spored id
+    }
+
+    @RequestMapping(value = "/thread/{postId}", method = RequestMethod.GET)
+    public _Thread getThreadById(@PathVariable Long postId) {
+        return mainService.get_ThreadById(postId); // vrakja thread (tema) spored id
+    }
+
     @RequestMapping(value = "/loginSuccessRegular", method = RequestMethod.GET)
     public Map<String, String> loginSuccessRegular(@RequestParam String sessionId) {
Index: springapp/src/main/java/mk/profesori/springapp/Controller/SecureController.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Controller/SecureController.java	(revision 8d831804abcee99d72c207c57a8f16e54b1329a2)
+++ springapp/src/main/java/mk/profesori/springapp/Controller/SecureController.java	(revision c68150fac8ab8e6f5dc5b8b2a9cd73d391dc1aa7)
@@ -1,35 +1,27 @@
 package mk.profesori.springapp.Controller;
 
-import java.util.Collections;
-import java.util.Map;
-
-import org.springframework.beans.factory.annotation.Autowired;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import mk.profesori.springapp.Model.CustomUserDetails;
+import mk.profesori.springapp.Service.CustomUserDetailsService;
+import mk.profesori.springapp.Service.MainService;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.annotation.CurrentSecurityContext;
 import org.springframework.security.core.context.SecurityContext;
 import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.web.bind.annotation.CrossOrigin;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
-
-import com.fasterxml.jackson.databind.node.ObjectNode;
-
-import mk.profesori.springapp.Model.CustomUserDetails;
-import mk.profesori.springapp.Service.CustomUserDetailsService;
-import mk.profesori.springapp.Service.MainService;
+import org.springframework.web.bind.annotation.*;
 
 @RestController
 @RequestMapping("/secure")
-@CrossOrigin(origins = { "http://192.168.0.17:3000", "http://192.168.0.28:3000" })
+@CrossOrigin(origins = { "http://192.168.0.17:3000", "http://192.168.0.39:3000" })
 public class SecureController {
 
-    @Autowired
-    private MainService mainService;
-    @Autowired
+    private final MainService mainService;
+    final
     CustomUserDetailsService customUserDetailsService;
+
+    public SecureController(MainService mainService, CustomUserDetailsService customUserDetailsService) {
+        this.mainService = mainService;
+        this.customUserDetailsService = customUserDetailsService;
+    }
 
     @RequestMapping(value = "/professor/{professorId}/addOpinion", method = RequestMethod.POST)
@@ -39,9 +31,7 @@
         Authentication authentication = context.getAuthentication();
 
-        if (authentication != null && authentication.getPrincipal() instanceof CustomUserDetails) {
-            CustomUserDetails currentUser = (CustomUserDetails) authentication.getPrincipal();
-            String title = objectNode.get("title").asText();
+        if (authentication != null && authentication.getPrincipal() instanceof CustomUserDetails currentUser) {
             String content = objectNode.get("content").asText();
-            mainService.addOpinion(title, content, professorId, currentUser);
+            mainService.addOpinion(content, professorId, currentUser);
         }
     }
@@ -53,8 +43,32 @@
         Authentication authentication = context.getAuthentication();
 
-        if (authentication != null && authentication.getPrincipal() instanceof CustomUserDetails) {
-            CustomUserDetails currentUser = (CustomUserDetails) authentication.getPrincipal();
+        if (authentication != null && authentication.getPrincipal() instanceof CustomUserDetails currentUser) {
             String content = objectNode.get("content").asText();
             mainService.replyToOpinion(content, professorId, postId, currentUser);
+        }
+    }
+
+    @RequestMapping(value = "/subject/{subjectId}/addThread", method = RequestMethod.POST)
+    public void addThread(@RequestBody ObjectNode objectNode, @PathVariable Long subjectId,
+            @CurrentSecurityContext SecurityContext context) {
+
+        Authentication authentication = context.getAuthentication();
+
+        if (authentication != null && authentication.getPrincipal() instanceof CustomUserDetails currentUser) {
+            String title = objectNode.get("title").asText();
+            String content = objectNode.get("content").asText();
+            mainService.addThread(title, content, subjectId, currentUser);
+        }
+    }
+
+    @RequestMapping(value = "/subject/{subjectId}/replyToThread/{postId}", method = RequestMethod.POST)
+    public void replyToThread(@RequestBody ObjectNode objectNode, @PathVariable Long subjectId,
+            @PathVariable Long postId, @CurrentSecurityContext SecurityContext context) {
+
+        Authentication authentication = context.getAuthentication();
+
+        if (authentication != null && authentication.getPrincipal() instanceof CustomUserDetails currentUser) {
+            String content = objectNode.get("content").asText();
+            mainService.replyToThread(content, subjectId, postId, currentUser);
         }
     }
@@ -64,6 +78,5 @@
 
         Authentication authentication = context.getAuthentication();
-        if (authentication != null && authentication.getPrincipal() instanceof CustomUserDetails) {
-            CustomUserDetails currentUser = (CustomUserDetails) authentication.getPrincipal();
+        if (authentication != null && authentication.getPrincipal() instanceof CustomUserDetails currentUser) {
             return customUserDetailsService.loadUserByUsername(currentUser.getEmail());
         }
@@ -72,27 +85,43 @@
     }
 
-    @RequestMapping(value = "/professor/{professorId}/upvoteOpinion/{postId}", method = RequestMethod.GET)
-    public void upvoteOpinion(@PathVariable Long professorId,
-            @PathVariable Long postId, @CurrentSecurityContext SecurityContext context) {
+    @RequestMapping(value = "/upvoteOpinion/{postId}", method = RequestMethod.GET)
+    public void upvoteOpinion(@PathVariable Long postId, @CurrentSecurityContext SecurityContext context) {
 
         Authentication authentication = context.getAuthentication();
 
-        if (authentication != null && authentication.getPrincipal() instanceof CustomUserDetails) {
-            CustomUserDetails currentUser = (CustomUserDetails) authentication.getPrincipal();
+        if (authentication != null && authentication.getPrincipal() instanceof CustomUserDetails currentUser) {
             mainService.upvoteOpinion(postId, currentUser);
         }
     }
 
-    @RequestMapping(value = "/professor/{professorId}/downvoteOpinion/{postId}", method = RequestMethod.GET)
-    public void downvoteOpinion(@PathVariable Long professorId,
-            @PathVariable Long postId, @CurrentSecurityContext SecurityContext context) {
+    @RequestMapping(value = "/downvoteOpinion/{postId}", method = RequestMethod.GET)
+    public void downvoteOpinion(@PathVariable Long postId, @CurrentSecurityContext SecurityContext context) {
 
         Authentication authentication = context.getAuthentication();
 
-        if (authentication != null && authentication.getPrincipal() instanceof CustomUserDetails) {
-            CustomUserDetails currentUser = (CustomUserDetails) authentication.getPrincipal();
+        if (authentication != null && authentication.getPrincipal() instanceof CustomUserDetails currentUser) {
             mainService.downvoteOpinion(postId, currentUser);
         }
     }
 
+    @RequestMapping(value = "/upvoteThread/{postId}", method = RequestMethod.GET)
+    public void upvoteThread(@PathVariable Long postId, @CurrentSecurityContext SecurityContext context) {
+
+        Authentication authentication = context.getAuthentication();
+
+        if (authentication != null && authentication.getPrincipal() instanceof CustomUserDetails currentUser) {
+            mainService.upvote_Thread(postId, currentUser);
+        }
+    }
+
+    @RequestMapping(value = "/downvoteThread/{postId}", method = RequestMethod.GET)
+    public void downvoteThread(@PathVariable Long postId, @CurrentSecurityContext SecurityContext context) {
+
+        Authentication authentication = context.getAuthentication();
+
+        if (authentication != null && authentication.getPrincipal() instanceof CustomUserDetails currentUser) {
+            mainService.downvote_Thread(postId, currentUser);
+        }
+    }
+
 }
Index: springapp/src/main/java/mk/profesori/springapp/Model/ConfirmationToken.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Model/ConfirmationToken.java	(revision 8d831804abcee99d72c207c57a8f16e54b1329a2)
+++ springapp/src/main/java/mk/profesori/springapp/Model/ConfirmationToken.java	(revision c68150fac8ab8e6f5dc5b8b2a9cd73d391dc1aa7)
@@ -12,4 +12,7 @@
 import javax.persistence.SequenceGenerator;
 
+import com.fasterxml.jackson.annotation.JsonIdentityInfo;
+import com.voodoodyne.jackson.jsog.JSOGGenerator;
+
 import lombok.Getter;
 import lombok.NoArgsConstructor;
@@ -20,6 +23,7 @@
 @NoArgsConstructor
 @Entity
+@JsonIdentityInfo(generator = JSOGGenerator.class)
 public class ConfirmationToken {
-    
+
     @Id
     @SequenceGenerator(name = "confirmation_token_sequence", sequenceName = "confirmation_token_sequence", allocationSize = 1)
@@ -42,7 +46,7 @@
     private CustomUserDetails customUserDetails;
 
-    public ConfirmationToken(String token, LocalDateTime createdAt, LocalDateTime expiredAt, 
-    CustomUserDetails customUserDetails) {
-        
+    public ConfirmationToken(String token, LocalDateTime createdAt, LocalDateTime expiredAt,
+            CustomUserDetails customUserDetails) {
+
         this.token = token;
         this.createdAt = createdAt;
Index: springapp/src/main/java/mk/profesori/springapp/Model/CustomUserDetails.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Model/CustomUserDetails.java	(revision 8d831804abcee99d72c207c57a8f16e54b1329a2)
+++ springapp/src/main/java/mk/profesori/springapp/Model/CustomUserDetails.java	(revision c68150fac8ab8e6f5dc5b8b2a9cd73d391dc1aa7)
@@ -1,36 +1,19 @@
 package mk.profesori.springapp.Model;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import javax.persistence.CascadeType;
-import javax.persistence.Entity;
-import javax.persistence.EnumType;
-import javax.persistence.Enumerated;
-import javax.persistence.FetchType;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.JoinTable;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToMany;
-import javax.persistence.OneToMany;
-import javax.persistence.SequenceGenerator;
-
+import com.fasterxml.jackson.annotation.JsonIdentityInfo;
+import com.voodoodyne.jackson.jsog.JSOGGenerator;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
 import org.springframework.security.core.GrantedAuthority;
 import org.springframework.security.core.authority.SimpleGrantedAuthority;
 import org.springframework.security.core.userdetails.UserDetails;
 
-import com.fasterxml.jackson.annotation.JsonIdentityInfo;
-import com.voodoodyne.jackson.jsog.JSOGGenerator;
-
-import lombok.EqualsAndHashCode;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
+import javax.persistence.*;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
 
 @Getter
@@ -59,10 +42,15 @@
     private Set<Post> authoredPosts = new HashSet<>();
     private Integer karma = 0;
-    @ManyToMany(fetch = FetchType.EAGER)
-    @JoinTable(name = "post_like", joinColumns = @JoinColumn(name = "custom_user_details_id"), inverseJoinColumns = @JoinColumn(name = "post_id"))
-    Set<Post> likedPosts;
-    @ManyToMany(fetch = FetchType.EAGER)
-    @JoinTable(name = "post_dislike", joinColumns = @JoinColumn(name = "custom_user_details_id"), inverseJoinColumns = @JoinColumn(name = "post_id"))
-    Set<Post> dislikedPosts;
+
+    public Set<PostVote> getVotes() {
+        return votes;
+    }
+
+    public void setVotes(Set<PostVote> votes) {
+        this.votes = votes;
+    }
+
+    @OneToMany(mappedBy = "user")
+    private Set<PostVote> votes = new HashSet<>();
 
     public CustomUserDetails(String fullName, String username, String email, String password, UserRole userRole) {
@@ -122,18 +110,8 @@
     }
 
-    public Set<Post> getLikedPosts() {
-        return this.likedPosts;
+    @Override
+    public String toString() {
+        return this.id.toString();
     }
 
-    public void setLikedPosts(Set<Post> likedPosts) {
-        this.likedPosts = likedPosts;
-    }
-
-    public Set<Post> getDislikedPosts() {
-        return this.dislikedPosts;
-    }
-
-    public void setDislikedPosts(Set<Post> dislikedPosts) {
-        this.likedPosts = dislikedPosts;
-    }
 }
Index: springapp/src/main/java/mk/profesori/springapp/Model/Post.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Model/Post.java	(revision 8d831804abcee99d72c207c57a8f16e54b1329a2)
+++ springapp/src/main/java/mk/profesori/springapp/Model/Post.java	(revision c68150fac8ab8e6f5dc5b8b2a9cd73d391dc1aa7)
@@ -3,4 +3,5 @@
 import java.time.LocalDateTime;
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -55,15 +56,20 @@
 
     @ManyToOne
-    @JoinColumn(name = "parent_post_id", nullable = true)
+    @JoinColumn(name = "parent_post_id")
     private Post parent;
+
+    @OneToMany(mappedBy = "post")
+    private Set<PostVote> votes = new HashSet<>();
+
+    public Set<PostVote> getVotes() {
+        return votes;
+    }
+
+    public void setVotes(Set<PostVote> votes) {
+        this.votes = votes;
+    }
 
     @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL)
     private List<Post> children = new ArrayList<>();
-
-    @ManyToMany(mappedBy = "likedPosts")
-    Set<CustomUserDetails> likes;
-
-    @ManyToMany(mappedBy = "dislikedPosts")
-    Set<CustomUserDetails> dislikes;
 
     // getters and setters
@@ -132,20 +138,4 @@
     }
 
-    public Set<CustomUserDetails> getLikes() {
-        return likes;
-    }
-
-    public void setLikes(Set<CustomUserDetails> likes) {
-        this.likes = likes;
-    }
-
-    public Set<CustomUserDetails> getDislikes() {
-        return dislikes;
-    }
-
-    public void setDislikes(Set<CustomUserDetails> dislikes) {
-        this.dislikes = dislikes;
-    }
-
     // konstruktor so parent (koga e reply)
     public Post(String title, String content, CustomUserDetails author, LocalDateTime timePosted,
@@ -174,3 +164,8 @@
     }
 
+    @Override
+    public String toString() {
+        return this.postId.toString();
+    }
+
 }
Index: springapp/src/main/java/mk/profesori/springapp/Model/PostVote.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Model/PostVote.java	(revision c68150fac8ab8e6f5dc5b8b2a9cd73d391dc1aa7)
+++ springapp/src/main/java/mk/profesori/springapp/Model/PostVote.java	(revision c68150fac8ab8e6f5dc5b8b2a9cd73d391dc1aa7)
@@ -0,0 +1,76 @@
+package mk.profesori.springapp.Model;
+
+import lombok.NoArgsConstructor;
+
+import javax.persistence.*;
+import java.time.LocalDateTime;
+
+@Entity
+@NoArgsConstructor
+public class PostVote {
+
+    @Id
+    @SequenceGenerator(name = "post_vote_sequence", sequenceName = "post_vote_sequence", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "post_vote_sequence")
+    private Long postVoteId;
+
+    @ManyToOne
+    @JoinColumn(name = "custom_user_details_id")
+    private CustomUserDetails user;
+
+    @ManyToOne
+    @JoinColumn(name = "post_id")
+    private Post post;
+
+    LocalDateTime time;
+
+    @Enumerated(EnumType.STRING)
+    private VoteType vote;
+
+    public PostVote(CustomUserDetails user, Post post, VoteType vote) {
+        this.user = user;
+        this.post = post;
+        this.time = LocalDateTime.now();
+        this.vote = vote;
+    }
+
+    public Long getPostVoteId() {
+        return postVoteId;
+    }
+
+    public void setPostVoteId(Long id) {
+        this.postVoteId = id;
+    }
+
+    public CustomUserDetails getUser() {
+        return user;
+    }
+
+    public void setUser(CustomUserDetails user) {
+        this.user = user;
+    }
+
+    public Post getPost() {
+        return post;
+    }
+
+    public void setPost(Post post) {
+        this.post = post;
+    }
+
+    public LocalDateTime getTime() {
+        return time;
+    }
+
+    public void setTime(LocalDateTime time) {
+        this.time = time;
+    }
+
+    public VoteType getVote() {
+        return vote;
+    }
+
+    public void setVote(VoteType vote) {
+        this.vote = vote;
+    }
+}
Index: springapp/src/main/java/mk/profesori/springapp/Model/Section.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Model/Section.java	(revision 8d831804abcee99d72c207c57a8f16e54b1329a2)
+++ 	(revision )
@@ -1,69 +1,0 @@
-package mk.profesori.springapp.Model;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.persistence.CascadeType;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.JoinColumn;
-import javax.persistence.OneToMany;
-import javax.persistence.OneToOne;
-
-import com.fasterxml.jackson.annotation.JsonIdentityInfo;
-import com.fasterxml.jackson.annotation.ObjectIdGenerators;
-
-@Entity
-@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "sectionId")
-public class Section {
-
-    @Id
-    @GeneratedValue(strategy = GenerationType.IDENTITY)
-    @Column(name = "id")
-    private Long sectionId;
-
-    @Column(name = "name")
-    private String name;
-
-    @OneToMany(mappedBy = "parentSection", cascade = CascadeType.ALL)
-    private List<_Thread> threads = new ArrayList<>();
-
-    @OneToOne
-    @JoinColumn(name = "study_programme_id", referencedColumnName = "id")
-    private StudyProgramme relatedStudyProgramme;
-
-    // getters and setters
-    public Long getSectionId() {
-        return sectionId;
-    }
-
-    public void setSectionId(Long sectionId) {
-        this.sectionId = sectionId;
-    }
-
-    public List<_Thread> getThreads() {
-        return threads;
-    }
-
-    public void setThreads(List<_Thread> threads) {
-        this.threads = threads;
-    }
-
-    public StudyProgramme getRelatedStudyProgramme() {
-        return relatedStudyProgramme;
-    }
-
-    public void setRelatedStudyProgramme(StudyProgramme relatedStudyProgramme) {
-        this.relatedStudyProgramme = relatedStudyProgramme;
-    }
-
-    public Section(Long sectionId, List<_Thread> threads, StudyProgramme relatedStudyProgramme) {
-        this.sectionId = sectionId;
-        this.threads = threads;
-        this.relatedStudyProgramme = relatedStudyProgramme;
-    }
-
-}
Index: springapp/src/main/java/mk/profesori/springapp/Model/StudyProgramme.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Model/StudyProgramme.java	(revision 8d831804abcee99d72c207c57a8f16e54b1329a2)
+++ springapp/src/main/java/mk/profesori/springapp/Model/StudyProgramme.java	(revision c68150fac8ab8e6f5dc5b8b2a9cd73d391dc1aa7)
@@ -12,5 +12,4 @@
 import javax.persistence.ManyToOne;
 import javax.persistence.OneToMany;
-import javax.persistence.OneToOne;
 import javax.persistence.Table;
 
@@ -41,7 +40,4 @@
     private Set<Subject> subjects = new HashSet<>();
 
-    @OneToOne(mappedBy = "relatedStudyProgramme")
-    private Section relatedSection;
-
     // getters
     public Long getStudyProgrammeId() {
@@ -65,6 +61,3 @@
     }
 
-    public Section getRelatedSection() {
-        return relatedSection;
-    }
 }
Index: springapp/src/main/java/mk/profesori/springapp/Model/Subject.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Model/Subject.java	(revision 8d831804abcee99d72c207c57a8f16e54b1329a2)
+++ springapp/src/main/java/mk/profesori/springapp/Model/Subject.java	(revision c68150fac8ab8e6f5dc5b8b2a9cd73d391dc1aa7)
@@ -15,9 +15,9 @@
 
 import com.fasterxml.jackson.annotation.JsonIdentityInfo;
-import com.fasterxml.jackson.annotation.ObjectIdGenerators;
+import com.voodoodyne.jackson.jsog.JSOGGenerator;
 
 @Entity
 @Table(name = "subject")
-@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "subjectId")
+@JsonIdentityInfo(generator = JSOGGenerator.class)
 public class Subject {
 
Index: springapp/src/main/java/mk/profesori/springapp/Model/University.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Model/University.java	(revision 8d831804abcee99d72c207c57a8f16e54b1329a2)
+++ springapp/src/main/java/mk/profesori/springapp/Model/University.java	(revision c68150fac8ab8e6f5dc5b8b2a9cd73d391dc1aa7)
@@ -15,9 +15,9 @@
 
 import com.fasterxml.jackson.annotation.JsonIdentityInfo;
-import com.fasterxml.jackson.annotation.ObjectIdGenerators;
+import com.voodoodyne.jackson.jsog.JSOGGenerator;
 
 @Entity
 @Table(name = "university")
-@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "universityId")
+@JsonIdentityInfo(generator = JSOGGenerator.class)
 public class University {
 
Index: springapp/src/main/java/mk/profesori/springapp/Model/VoteType.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Model/VoteType.java	(revision c68150fac8ab8e6f5dc5b8b2a9cd73d391dc1aa7)
+++ springapp/src/main/java/mk/profesori/springapp/Model/VoteType.java	(revision c68150fac8ab8e6f5dc5b8b2a9cd73d391dc1aa7)
@@ -0,0 +1,6 @@
+package mk.profesori.springapp.Model;
+
+public enum VoteType {
+    UPVOTE,
+    DOWNVOTE
+}
Index: springapp/src/main/java/mk/profesori/springapp/Model/_Thread.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Model/_Thread.java	(revision 8d831804abcee99d72c207c57a8f16e54b1329a2)
+++ springapp/src/main/java/mk/profesori/springapp/Model/_Thread.java	(revision c68150fac8ab8e6f5dc5b8b2a9cd73d391dc1aa7)
@@ -2,25 +2,19 @@
 
 import java.time.LocalDateTime;
-import java.util.ArrayList;
+
 import java.util.List;
 
-import javax.persistence.Column;
 import javax.persistence.DiscriminatorValue;
-import javax.persistence.ElementCollection;
+
 import javax.persistence.Entity;
 import javax.persistence.JoinColumn;
 import javax.persistence.ManyToOne;
 
+import lombok.NoArgsConstructor;
+
 @Entity
 @DiscriminatorValue("thread")
+@NoArgsConstructor
 public class _Thread extends Post {
-
-    @Column(name = "tags") // unused
-    @ElementCollection
-    private List<String> tags = new ArrayList<>();
-
-    @ManyToOne
-    @JoinColumn(name = "section_id")
-    private Section parentSection;
 
     @ManyToOne
@@ -31,7 +25,6 @@
     public _Thread(String title, String content, CustomUserDetails author, LocalDateTime timePosted,
             LocalDateTime timeLastEdited,
-            Post parent, List<Post> children, Section parentSection, Subject targetSubject) {
+            Post parent, List<Post> children, Subject targetSubject) {
         super(title, content, author, timePosted, timeLastEdited, parent, children);
-        this.parentSection = parentSection;
         this.targetSubject = targetSubject;
     }
@@ -39,17 +32,7 @@
     // konstruktor bez parent (koga NE e reply)
     public _Thread(String title, String content, CustomUserDetails author, LocalDateTime timePosted,
-            LocalDateTime timeLastEdited, List<Post> children, Section parentSection, Subject targetSubject) {
+            LocalDateTime timeLastEdited, List<Post> children, Subject targetSubject) {
         super(title, content, author, timePosted, timeLastEdited, children);
-        this.parentSection = parentSection;
         this.targetSubject = targetSubject;
-    }
-
-    // getters
-    public List<String> getTags() {
-        return tags;
-    }
-
-    public Section getParentSection() {
-        return parentSection;
     }
 
Index: springapp/src/main/java/mk/profesori/springapp/Repository/OpinionRepository.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Repository/OpinionRepository.java	(revision 8d831804abcee99d72c207c57a8f16e54b1329a2)
+++ springapp/src/main/java/mk/profesori/springapp/Repository/OpinionRepository.java	(revision c68150fac8ab8e6f5dc5b8b2a9cd73d391dc1aa7)
@@ -1,11 +1,10 @@
 package mk.profesori.springapp.Repository;
 
+import mk.profesori.springapp.Model.Opinion;
 import org.springframework.data.repository.CrudRepository;
 import org.springframework.stereotype.Repository;
 
-import mk.profesori.springapp.Model.Opinion;
-
 @Repository
-public interface OpinionRepository extends CrudRepository<Opinion, Long> {
-    public Opinion findByPostId(Long id);
+public interface OpinionRepository extends CrudRepository<Opinion,Long> {
+    Opinion findByPostId(Long postId);
 }
Index: springapp/src/main/java/mk/profesori/springapp/Repository/PostVoteRepository.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Repository/PostVoteRepository.java	(revision c68150fac8ab8e6f5dc5b8b2a9cd73d391dc1aa7)
+++ springapp/src/main/java/mk/profesori/springapp/Repository/PostVoteRepository.java	(revision c68150fac8ab8e6f5dc5b8b2a9cd73d391dc1aa7)
@@ -0,0 +1,10 @@
+package mk.profesori.springapp.Repository;
+
+import mk.profesori.springapp.Model.PostVote;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface PostVoteRepository extends CrudRepository<PostVote,Long> {
+    PostVote findByPostVoteId(Long id);
+}
Index: springapp/src/main/java/mk/profesori/springapp/Repository/SubjectRepository.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Repository/SubjectRepository.java	(revision c68150fac8ab8e6f5dc5b8b2a9cd73d391dc1aa7)
+++ springapp/src/main/java/mk/profesori/springapp/Repository/SubjectRepository.java	(revision c68150fac8ab8e6f5dc5b8b2a9cd73d391dc1aa7)
@@ -0,0 +1,11 @@
+package mk.profesori.springapp.Repository;
+
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Repository;
+
+import mk.profesori.springapp.Model.Subject;
+
+@Repository
+public interface SubjectRepository extends CrudRepository<Subject, Long> {
+    public Subject findBySubjectId(Long id);
+}
Index: springapp/src/main/java/mk/profesori/springapp/Repository/_ThreadRepository.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Repository/_ThreadRepository.java	(revision c68150fac8ab8e6f5dc5b8b2a9cd73d391dc1aa7)
+++ springapp/src/main/java/mk/profesori/springapp/Repository/_ThreadRepository.java	(revision c68150fac8ab8e6f5dc5b8b2a9cd73d391dc1aa7)
@@ -0,0 +1,10 @@
+package mk.profesori.springapp.Repository;
+
+import mk.profesori.springapp.Model._Thread;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface _ThreadRepository extends CrudRepository<_Thread,Long> {
+    _Thread findByPostId(Long postId);
+}
Index: springapp/src/main/java/mk/profesori/springapp/Security/SecurityConfiguration.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Security/SecurityConfiguration.java	(revision 8d831804abcee99d72c207c57a8f16e54b1329a2)
+++ springapp/src/main/java/mk/profesori/springapp/Security/SecurityConfiguration.java	(revision c68150fac8ab8e6f5dc5b8b2a9cd73d391dc1aa7)
@@ -37,5 +37,5 @@
             @Override
             public void addCorsMappings(CorsRegistry registry) {
-                registry.addMapping("/**").allowedOrigins("http://192.168.0.17:3000", "http://192.168.0.28:3000")
+                registry.addMapping("/**").allowedOrigins("http://192.168.0.17:3000", "http://192.168.0.39:3000")
                         .allowCredentials(true);
             }
Index: springapp/src/main/java/mk/profesori/springapp/Service/EmailValidator.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Service/EmailValidator.java	(revision 8d831804abcee99d72c207c57a8f16e54b1329a2)
+++ springapp/src/main/java/mk/profesori/springapp/Service/EmailValidator.java	(revision c68150fac8ab8e6f5dc5b8b2a9cd73d391dc1aa7)
@@ -13,5 +13,5 @@
     public boolean test(String email) {
         
-        String regex = "^(.+)@(.+)$";
+        String regex = "^(.+)@(.+)$"; //TODO bilosto@@ ->> illegal address exception od mailsender
 
         Pattern pattern = Pattern.compile(regex);
Index: springapp/src/main/java/mk/profesori/springapp/Service/MainService.java
===================================================================
--- springapp/src/main/java/mk/profesori/springapp/Service/MainService.java	(revision 8d831804abcee99d72c207c57a8f16e54b1329a2)
+++ springapp/src/main/java/mk/profesori/springapp/Service/MainService.java	(revision c68150fac8ab8e6f5dc5b8b2a9cd73d391dc1aa7)
@@ -1,48 +1,41 @@
 package mk.profesori.springapp.Service;
+
+import mk.profesori.springapp.Model.*;
+import mk.profesori.springapp.Repository.*;
+import org.springframework.stereotype.Service;
 
 import java.util.ArrayList;
 import java.util.List;
 
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-import mk.profesori.springapp.Repository.CityRepository;
-import mk.profesori.springapp.Repository.FacultyRepository;
-import mk.profesori.springapp.Repository.OpinionRepository;
-import mk.profesori.springapp.Repository.ProfessorRepository;
-import mk.profesori.springapp.Repository.StudyProgrammeRepository;
-import mk.profesori.springapp.Repository.UniversityRepository;
-import mk.profesori.springapp.Repository.UserRepository;
-import mk.profesori.springapp.Model.City;
-import mk.profesori.springapp.Model.CustomUserDetails;
-import mk.profesori.springapp.Model.Faculty;
-import mk.profesori.springapp.Model.Opinion;
-import mk.profesori.springapp.Model.Professor;
-import mk.profesori.springapp.Model.StudyProgramme;
-import mk.profesori.springapp.Model.University;
-
 @Service
 public class MainService {
 
-    @Autowired
-    private ProfessorRepository professorRepository;
-    @Autowired
-    private StudyProgrammeRepository studyProgrammeRepository;
-    @Autowired
-    private FacultyRepository facultyRepository;
-    @Autowired
-    private UniversityRepository universityRepository;
-    @Autowired
-    private CityRepository cityRepository;
-    @Autowired
-    private OpinionRepository opinionRepository;
-    @Autowired
-    private UserRepository userRepository;
+    private final ProfessorRepository professorRepository;
+    private final StudyProgrammeRepository studyProgrammeRepository;
+    private final FacultyRepository facultyRepository;
+    private final UniversityRepository universityRepository;
+    private final CityRepository cityRepository;
+    private final OpinionRepository opinionRepository;
+    private final _ThreadRepository _threadRepository;
+    private final SubjectRepository subjectRepository;
+    private final PostVoteRepository postVoteRepository;
+    private final UserRepository userRepository;
+
+    public MainService(ProfessorRepository professorRepository, StudyProgrammeRepository studyProgrammeRepository, FacultyRepository facultyRepository, UniversityRepository universityRepository, CityRepository cityRepository, OpinionRepository opinionRepository, _ThreadRepository _threadRepository, SubjectRepository subjectRepository, PostVoteRepository postVoteRepository, UserRepository userRepository) {
+        this.professorRepository = professorRepository;
+        this.studyProgrammeRepository = studyProgrammeRepository;
+        this.facultyRepository = facultyRepository;
+        this.universityRepository = universityRepository;
+        this.cityRepository = cityRepository;
+        this.opinionRepository = opinionRepository;
+        this._threadRepository = _threadRepository;
+        this.subjectRepository = subjectRepository;
+        this.postVoteRepository = postVoteRepository;
+        this.userRepository = userRepository;
+    }
 
     public List<Professor> getAllProfessors() {
 
-        List<Professor> list = new ArrayList<>();
-        professorRepository.findAll().forEach(list::add);
-        return list;
+        return new ArrayList<>(professorRepository.findAll());
     }
 
@@ -56,20 +49,14 @@
         Faculty faculty = facultyRepository.findByFacultyId(facultyId);
 
-        List<Professor> list = new ArrayList<>();
-        professorRepository.findByFaculty(faculty).forEach(list::add);
-        return list;
+        return new ArrayList<>(professorRepository.findByFaculty(faculty));
     }
 
     public List<Professor> getProfessorsByNameContains(String contained) {
-        List<Professor> list = new ArrayList<>();
-        professorRepository.findByProfessorNameContainingIgnoreCase(contained).forEach(list::add);
-        return list;
+        return new ArrayList<>(professorRepository.findByProfessorNameContainingIgnoreCase(contained));
     }
 
     public List<StudyProgramme> getAllStudyProgrammes() {
 
-        List<StudyProgramme> list = new ArrayList<>();
-        studyProgrammeRepository.findAll().forEach(list::add);
-        return list;
+        return new ArrayList<>(studyProgrammeRepository.findAll());
     }
 
@@ -83,13 +70,9 @@
         Faculty faculty = facultyRepository.findByFacultyId(facultyId);
 
-        List<StudyProgramme> list = new ArrayList<>();
-        studyProgrammeRepository.findByFaculty(faculty).forEach(list::add);
-        return list;
+        return new ArrayList<>(studyProgrammeRepository.findByFaculty(faculty));
     }
 
     public List<Faculty> getAllFaculties() {
-        List<Faculty> list = new ArrayList<>();
-        facultyRepository.findAll().forEach(list::add);
-        return list;
+        return new ArrayList<>(facultyRepository.findAll());
     }
 
@@ -102,13 +85,9 @@
         University university = universityRepository.findByUniversityId(universityId);
 
-        List<Faculty> list = new ArrayList<>();
-        facultyRepository.findByUniversity(university).forEach(list::add);
-        return list;
+        return new ArrayList<>(facultyRepository.findByUniversity(university));
     }
 
     public List<University> getAllUniversities() {
-        List<University> list = new ArrayList<>();
-        universityRepository.findAll().forEach(list::add);
-        return list;
+        return new ArrayList<>(universityRepository.findAll());
     }
 
@@ -121,13 +100,9 @@
         City city = cityRepository.findByCityId(cityId);
 
-        List<University> list = new ArrayList<>();
-        universityRepository.findByCity(city).forEach(list::add);
-        return list;
+        return new ArrayList<>(universityRepository.findByCity(city));
     }
 
     public List<City> getAllCities() {
-        List<City> list = new ArrayList<>();
-        cityRepository.findAll().forEach(list::add);
-        return list;
+        return new ArrayList<>(cityRepository.findAll());
     }
 
@@ -136,9 +111,9 @@
     }
 
-    public void addOpinion(String title, String content, Long professorId, CustomUserDetails currentUser) {
+    public void addOpinion(String content, Long professorId, CustomUserDetails currentUser) {
 
         Professor targetProfessor = professorRepository.findByProfessorId(professorId);
 
-        Opinion opinionToAdd = new Opinion(title, content, currentUser, null, null,
+        Opinion opinionToAdd = new Opinion(null, content, currentUser, null, null,
                 null, targetProfessor);
 
@@ -155,38 +130,65 @@
         opinionRepository.save(opinionToAdd);
 
+        //mozda ne treba
         targetOpinion.getChildren().add(opinionToAdd);
         opinionRepository.save(targetOpinion);
     }
 
-    public void upvoteOpinion(Long postId, CustomUserDetails currentUser) {
-        Opinion targetOpinion = opinionRepository.findByPostId(postId);
+    public void addThread(String title, String content, Long subjectId, CustomUserDetails currentUser) {
+        Subject targetSubject = subjectRepository.findBySubjectId(subjectId);
 
-        if (!targetOpinion.getLikes().contains(currentUser)) {
-
-            targetOpinion.getLikes().add(currentUser);
-            // opinionRepository.save(targetOpinion);
-
-            targetOpinion.getAuthor().setKarma(targetOpinion.getAuthor().getKarma() + 1);
-            userRepository.save(targetOpinion.getAuthor());
-
-            currentUser.getLikedPosts().add(targetOpinion);
-            userRepository.save(currentUser);
-        }
+        _Thread _threadToAdd = new _Thread(title, content, currentUser, null, null, null, targetSubject);
+        _threadRepository.save(_threadToAdd);
     }
 
+    public void replyToThread(String content, Long subjectId, Long postId, CustomUserDetails currentUser) {
+        Subject targetSubject = subjectRepository.findBySubjectId(subjectId);
+        _Thread target_Thread = _threadRepository.findByPostId(postId);
+
+        _Thread _threadToAdd = new _Thread(null, content, currentUser, null, null, target_Thread, null, targetSubject);
+        _threadRepository.save(_threadToAdd);
+
+        //mozda ne treba
+        target_Thread.getChildren().add(_threadToAdd);
+        _threadRepository.save(target_Thread);
+    }
+
+    public Subject getSubjectById(Long subjectId) {
+        return subjectRepository.findBySubjectId(subjectId);
+    }
+
+    public _Thread get_ThreadById(Long postId) {
+        return _threadRepository.findByPostId(postId);
+    }
+
+    public void upvoteOpinion(Long postId, CustomUserDetails currentUser) {
+        Post targetPost = opinionRepository.findByPostId(postId);
+        PostVote voteToAdd = new PostVote(currentUser, targetPost, VoteType.UPVOTE);
+        postVoteRepository.save(voteToAdd);
+        targetPost.getAuthor().setKarma(targetPost.getAuthor().getKarma()+1);
+        userRepository.save(targetPost.getAuthor());
+    }
     public void downvoteOpinion(Long postId, CustomUserDetails currentUser) {
-        Opinion targetOpinion = opinionRepository.findByPostId(postId);
+        Post targetPost = opinionRepository.findByPostId(postId);
+        PostVote voteToAdd = new PostVote(currentUser, targetPost, VoteType.DOWNVOTE);
+        postVoteRepository.save(voteToAdd);
+        targetPost.getAuthor().setKarma(targetPost.getAuthor().getKarma()-1);
+        userRepository.save(targetPost.getAuthor());
+    }
 
-        if (!targetOpinion.getDislikes().contains(currentUser)) {
+    public void upvote_Thread(Long postId, CustomUserDetails currentUser) {
+        Post targetPost = _threadRepository.findByPostId(postId);
+        PostVote voteToAdd = new PostVote(currentUser, targetPost, VoteType.UPVOTE);
+        postVoteRepository.save(voteToAdd);
+        targetPost.getAuthor().setKarma(targetPost.getAuthor().getKarma()+1);
+        userRepository.save(targetPost.getAuthor());
 
-            targetOpinion.getDislikes().add(currentUser);
-            // opinionRepository.save(targetOpinion);
-
-            targetOpinion.getAuthor().setKarma(targetOpinion.getAuthor().getKarma() - 1);
-            userRepository.save(targetOpinion.getAuthor());
-
-            currentUser.getDislikedPosts().add(targetOpinion);
-            userRepository.save(currentUser);
-        }
+    }
+    public void downvote_Thread(Long postId, CustomUserDetails currentUser) {
+        Post targetPost = _threadRepository.findByPostId(postId);
+        PostVote voteToAdd = new PostVote(currentUser, targetPost, VoteType.DOWNVOTE);
+        postVoteRepository.save(voteToAdd);
+        targetPost.getAuthor().setKarma(targetPost.getAuthor().getKarma()-1);
+        userRepository.save(targetPost.getAuthor());
     }
 }
Index: springapp/src/main/resources/application.properties
===================================================================
--- springapp/src/main/resources/application.properties	(revision 8d831804abcee99d72c207c57a8f16e54b1329a2)
+++ springapp/src/main/resources/application.properties	(revision c68150fac8ab8e6f5dc5b8b2a9cd73d391dc1aa7)
@@ -4,9 +4,9 @@
 spring.datasource.password=1win7337
 spring.jpa.hibernate.ddl-auto=update
+spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
 spring.jpa.show-sql=false
-spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
 spring.jpa.properties.hibernate.format_sql=true
 server.address=192.168.0.17
-spring.mail.host=192.168.0.28
+spring.mail.host=192.168.0.39
 spring.mail.username=mailuser
 spring.mail.password=mailpass
