diff --git a/mozen/pom.xml b/mozen/pom.xml
index bf20c95b04e2d683749b89d8d36631c7506092c8..956a989d57ce1bb584106b99046affd9c54ca124 100644
--- a/mozen/pom.xml
+++ b/mozen/pom.xml
@@ -31,6 +31,10 @@
 			<groupId>org.springframework.boot</groupId>
 			<artifactId>spring-boot-starter-web</artifactId>
 		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-security</artifactId>
+		</dependency>
 
 		<dependency>
 			<groupId>org.hsqldb</groupId>
diff --git a/mozen/src/main/java/mozen/MozenApplication.java b/mozen/src/main/java/mozen/MozenApplication.java
index 69466a1db3dfd009b49f1b98a8df17073c77a02f..68b4c2a9bfda296679a92c32ea62661444721104 100644
--- a/mozen/src/main/java/mozen/MozenApplication.java
+++ b/mozen/src/main/java/mozen/MozenApplication.java
@@ -3,13 +3,20 @@ package mozen;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.autoconfigure.domain.EntityScan;
+import org.springframework.context.annotation.Bean;
 import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 
 @SpringBootApplication
 @EnableJpaRepositories(basePackageClasses = MozenApplication.class)
 @EntityScan(basePackageClasses = MozenApplication.class)
 public class MozenApplication {
 
+	@Bean
+	public BCryptPasswordEncoder bCryptPasswordEncoder() {
+		return new BCryptPasswordEncoder();
+	}
+
 	public static void main(String[] args) {
 		SpringApplication.run(MozenApplication.class, args);
 	}
diff --git a/mozen/src/main/java/mozen/auth/JwtAuthenticationFilter.java b/mozen/src/main/java/mozen/auth/JwtAuthenticationFilter.java
new file mode 100644
index 0000000000000000000000000000000000000000..1a46cd4476f18b0f0c684f54aa3cf45a189e8c4e
--- /dev/null
+++ b/mozen/src/main/java/mozen/auth/JwtAuthenticationFilter.java
@@ -0,0 +1,71 @@
+package mozen.auth;
+
+import java.io.IOException;
+import java.security.Key;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.util.ArrayList;
+import java.util.Date;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+import mozen.model.LoginMessage;
+import mozen.utils.KeyGenerator;
+
+public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter{
+  private AuthenticationManager authenticationManager;
+
+  public JwtAuthenticationFilter(AuthenticationManager authenticationManager){
+    this.authenticationManager = authenticationManager;
+  }
+
+  @Override
+  public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res) throws AuthenticationException {
+    try {
+      LoginMessage message = new ObjectMapper().readValue(req.getInputStream(), LoginMessage.class);
+
+      System.err.println("Auth user n:"+message.getUsername()+" p:"+message.getPassword());
+
+      return authenticationManager.authenticate(
+        new UsernamePasswordAuthenticationToken(message.getUsername(), message.getPassword(), new ArrayList<>())
+      );
+    } catch (IOException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  @Override
+  protected void successfulAuthentication(HttpServletRequest req, HttpServletResponse res, FilterChain chain, Authentication auth) 
+  throws IOException, ServletException {
+    User user = (User) auth.getPrincipal();
+    Key key = KeyGenerator.generateKey();
+    
+    String token = Jwts.builder()
+      .setSubject(user.getUsername())
+      .claim("username",user.getUsername())
+      .setIssuedAt(new Date())
+      .setExpiration(toDate(LocalDateTime.now().plusDays(1L)))
+      .signWith(SignatureAlgorithm.HS512, key)
+      .compact();
+    
+      res.addHeader("Authorization", "Bearer " + token);
+  }
+
+  private Date toDate(LocalDateTime localDateTime) {
+    return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
+  }
+}
\ No newline at end of file
diff --git a/mozen/src/main/java/mozen/auth/JwtAuthorizationFilter.java b/mozen/src/main/java/mozen/auth/JwtAuthorizationFilter.java
new file mode 100644
index 0000000000000000000000000000000000000000..963fc3206a7654327d302d4c4b2f724f6da35a2c
--- /dev/null
+++ b/mozen/src/main/java/mozen/auth/JwtAuthorizationFilter.java
@@ -0,0 +1,61 @@
+package mozen.auth;
+
+import java.io.IOException;
+import java.security.Key;
+import java.util.ArrayList;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
+
+import io.jsonwebtoken.Jwts;
+import mozen.utils.KeyGenerator;
+
+public class JwtAuthorizationFilter extends BasicAuthenticationFilter {
+
+  public JwtAuthorizationFilter(AuthenticationManager authenticationManager) {
+    super(authenticationManager);
+  }
+
+  @Override
+  protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) 
+  throws IOException, ServletException {
+    String header = request.getHeader("Authorization");
+
+    if(header == null || !header.startsWith("Bearer ")) {
+      chain.doFilter(request, response);
+      return;
+    }
+
+    UsernamePasswordAuthenticationToken auth = getAuthentication(request);
+    SecurityContextHolder.getContext().setAuthentication(auth);
+    
+    chain.doFilter(request, response);
+  }
+
+  private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
+    String token = request.getHeader("Authorization");
+    if(token != null) {
+      Key key = KeyGenerator.generateKey();
+      String username = Jwts.parser()
+        .setSigningKey(key)
+        .parseClaimsJws(token.replace("Bearer ", ""))
+        .getBody()
+        .getSubject();
+
+      if (username != null) {
+        return new UsernamePasswordAuthenticationToken(username, null, new ArrayList<>());
+      }
+
+      return null;
+    }
+    return null;
+  }
+
+}
\ No newline at end of file
diff --git a/mozen/src/main/java/mozen/auth/JwtUserDetailsService.java b/mozen/src/main/java/mozen/auth/JwtUserDetailsService.java
new file mode 100644
index 0000000000000000000000000000000000000000..a6bc4da74f2149fd215a301d2a6380f126e02b02
--- /dev/null
+++ b/mozen/src/main/java/mozen/auth/JwtUserDetailsService.java
@@ -0,0 +1,26 @@
+package mozen.auth;
+
+import java.util.ArrayList;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.stereotype.Service;
+
+import mozen.business.IUserManager;
+
+@Service
+public class JwtUserDetailsService implements UserDetailsService {
+  @Autowired
+  IUserManager manager;
+
+  @Override
+  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
+    mozen.model.User user = manager.getUserByUsername(username);
+    if(user == null) throw new UsernameNotFoundException(username);
+    return new User(user.getUsername(), user.getPassword(), new ArrayList<>());
+  }
+  
+}
\ No newline at end of file
diff --git a/mozen/src/main/java/mozen/auth/WebSecurity.java b/mozen/src/main/java/mozen/auth/WebSecurity.java
new file mode 100644
index 0000000000000000000000000000000000000000..9b243b1cddc59b8d61e92d51878d2854a4477cd7
--- /dev/null
+++ b/mozen/src/main/java/mozen/auth/WebSecurity.java
@@ -0,0 +1,38 @@
+package mozen.auth;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpMethod;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+
+@EnableWebSecurity
+public class WebSecurity extends WebSecurityConfigurerAdapter{
+  @Autowired
+  private JwtUserDetailsService userDetailsService;
+
+  @Autowired
+  private BCryptPasswordEncoder bCryptPasswordEncoder;
+
+  @Override
+  protected void configure(HttpSecurity http) throws Exception {
+    http.cors().and().csrf().disable().authorizeRequests()
+        .antMatchers(HttpMethod.POST, "/user/signup").permitAll()
+        .antMatchers(HttpMethod.GET, "/search").permitAll()
+        .antMatchers(HttpMethod.GET, "/models").permitAll()
+        .antMatchers(HttpMethod.GET, "/models/tags").permitAll()
+        .anyRequest().authenticated()
+        .and()
+        .addFilter(new JwtAuthenticationFilter(authenticationManager()))
+        .addFilter(new JwtAuthorizationFilter(authenticationManager()))
+        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
+  }
+
+  @Override
+  public void configure(AuthenticationManagerBuilder auth) throws Exception {
+    auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
+  }
+}
\ No newline at end of file
diff --git a/mozen/src/main/java/mozen/business/IModelDao.java b/mozen/src/main/java/mozen/business/IModelDao.java
index cfb559e077005abe9aed74e496bd12fc5865f4f9..709de7260db0e99597876491a56847c86f9e040a 100644
--- a/mozen/src/main/java/mozen/business/IModelDao.java
+++ b/mozen/src/main/java/mozen/business/IModelDao.java
@@ -3,14 +3,14 @@ package mozen.business;
 import java.util.Collection;
 
 import mozen.model.Model;
-import mozen.model.Tag;
+import mozen.model.TagCategory;
 
 public interface IModelDao {
   void addModel(Model m);
   void updateModel(Model m);
   void removeModel(long id);
 
-  Collection<Tag> getTags();
+  Collection<TagCategory> getTags();
 
   Model findModel(long id);
   Collection<Model> findModelsByName(String name);
diff --git a/mozen/src/main/java/mozen/business/IModelManager.java b/mozen/src/main/java/mozen/business/IModelManager.java
index de8745048963b32ed1ca3c0e20697ec0ea4971fa..87d62fa0143094fd4578c5dc3a5e9f8f7cde9723 100644
--- a/mozen/src/main/java/mozen/business/IModelManager.java
+++ b/mozen/src/main/java/mozen/business/IModelManager.java
@@ -3,7 +3,7 @@ package mozen.business;
 import java.util.Collection;
 
 import mozen.model.Model;
-import mozen.model.Tag;
+import mozen.model.TagCategory;
 
 public interface IModelManager {
   Long addModel(Model m);
@@ -11,6 +11,6 @@ public interface IModelManager {
   void removeModel(Long id);
 
   Model getModel(Long id);
-  Collection<Tag> getTags();
+  Collection<TagCategory> getTags();
   Collection<Model> findModel(String name);
 }
\ No newline at end of file
diff --git a/mozen/src/main/java/mozen/business/IUserDao.java b/mozen/src/main/java/mozen/business/IUserDao.java
index aed55a5561da3f12332f64be2aa9a2f2723f1618..cef4958a8291d2b9a8118e231c2c968d8656ec07 100644
--- a/mozen/src/main/java/mozen/business/IUserDao.java
+++ b/mozen/src/main/java/mozen/business/IUserDao.java
@@ -8,5 +8,5 @@ public interface IUserDao {
   void removeUser(long id);
   
   User findUser(long id);
-  User findUserByMail(String email);
+  User findUserByUsername(String username);
 }
\ No newline at end of file
diff --git a/mozen/src/main/java/mozen/business/IUserManager.java b/mozen/src/main/java/mozen/business/IUserManager.java
index fa311b1ed91d1bca95a1d2f654993662230e73ee..072835b9477a7c53051308cfc9f11c75b356d84d 100644
--- a/mozen/src/main/java/mozen/business/IUserManager.java
+++ b/mozen/src/main/java/mozen/business/IUserManager.java
@@ -1,15 +1,17 @@
 package mozen.business;
 
+import mozen.model.SignupMessage;
 import mozen.model.User;
 
 public interface IUserManager {
-  Long addUser(User u);
+  Long addUser(SignupMessage message);
   void updateUser(User u);
   void removeUser(Long id);
 
   User getUser(Long id);
+  User getUserByUsername(String username);
 
-  String logUser(String email, String password);
+  
   boolean resetPassword(String email);
   boolean changePassword(String token, String password);
 }
\ No newline at end of file
diff --git a/mozen/src/main/java/mozen/business/ModelDao.java b/mozen/src/main/java/mozen/business/ModelDao.java
index 482b58e81e14af0352c438010053a7bc35f02b0d..044ab9f92ada199f3212c529e112c0b82522390d 100644
--- a/mozen/src/main/java/mozen/business/ModelDao.java
+++ b/mozen/src/main/java/mozen/business/ModelDao.java
@@ -11,7 +11,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Repository;
 
 import mozen.model.Model;
-import mozen.model.Tag;
+import mozen.model.TagCategory;
 
 @Repository
 @Transactional
@@ -55,9 +55,9 @@ public class ModelDao implements IModelDao {
   }
 
   @Override
-  public Collection<Tag> getTags() {
-    String query = "SELECT t FROM Tag t";
-		TypedQuery<Tag> q = em.createQuery(query, Tag.class);
+  public Collection<TagCategory> getTags() {
+    String query = "SELECT t FROM TagCategory t";
+		TypedQuery<TagCategory> q = em.createQuery(query, TagCategory.class);
 		try {
 			return q.getResultList();
 		} catch (Exception e) {
diff --git a/mozen/src/main/java/mozen/business/ModelManager.java b/mozen/src/main/java/mozen/business/ModelManager.java
index b1c5a40f0936f353a5a2c0e9d48748413d560899..fbd4e639e3198880ca2e745360fb7109507772c9 100644
--- a/mozen/src/main/java/mozen/business/ModelManager.java
+++ b/mozen/src/main/java/mozen/business/ModelManager.java
@@ -6,7 +6,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import mozen.model.Model;
-import mozen.model.Tag;
+import mozen.model.TagCategory;
 
 @Service
 public class ModelManager implements IModelManager {
@@ -43,7 +43,7 @@ public class ModelManager implements IModelManager {
   }
 
   @Override
-  public Collection<Tag> getTags() {
+  public Collection<TagCategory> getTags() {
     return dao.getTags();
   }
   
diff --git a/mozen/src/main/java/mozen/business/UserDao.java b/mozen/src/main/java/mozen/business/UserDao.java
index e5b7095603d14d2741b6d81b2030655f5d2a7874..dac133b97080427c86d7fe77b11531e7c5fe81a9 100644
--- a/mozen/src/main/java/mozen/business/UserDao.java
+++ b/mozen/src/main/java/mozen/business/UserDao.java
@@ -40,10 +40,10 @@ public class UserDao implements IUserDao {
   }
 
   @Override
-  public User findUserByMail(String email) {
-    String query = "SELECT u FROM User u WHERE u.email = : email";
+  public User findUserByUsername(String username) {
+    String query = "SELECT u FROM User u WHERE u.username = : username";
 		TypedQuery<User> q = em.createQuery(query, User.class);
-		q.setParameter("email", email);
+		q.setParameter("username", username);
 		try {
 			return q.getSingleResult();
 		} catch (Exception e) {
diff --git a/mozen/src/main/java/mozen/business/UserManager.java b/mozen/src/main/java/mozen/business/UserManager.java
index 188385614b88c9b940949aee1c7c317982a8ccaa..266da3d4c81949ebbc509e4c6ef852ad06ff8ccf 100644
--- a/mozen/src/main/java/mozen/business/UserManager.java
+++ b/mozen/src/main/java/mozen/business/UserManager.java
@@ -1,17 +1,11 @@
 package mozen.business;
 
-import java.security.Key;
-import java.time.LocalDateTime;
-import java.time.ZoneId;
-import java.util.Date;
-
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 import org.springframework.stereotype.Service;
 
-import io.jsonwebtoken.Jwts;
-import io.jsonwebtoken.SignatureAlgorithm;
+import mozen.model.SignupMessage;
 import mozen.model.User;
-import mozen.utils.KeyGenerator;
 
 @Service
 public class UserManager implements IUserManager {
@@ -19,8 +13,17 @@ public class UserManager implements IUserManager {
   @Autowired
   IUserDao dao;
 
+  @Autowired
+  BCryptPasswordEncoder bCryptPasswordEncoder;
+
   @Override
-  public Long addUser(User u) {
+  public Long addUser(SignupMessage message) {
+    User u = new User();
+    u.setEmail(message.getEmail());
+    u.setUsername(message.getUsername());
+    u.setPassword(bCryptPasswordEncoder.encode(message.getPassword()));
+    u.setRole("DEFAULT");
+
     dao.addUser(u);
     return u.getId();
   }
@@ -40,28 +43,6 @@ public class UserManager implements IUserManager {
     return dao.findUser(id);
   }
 
-  @Override
-  public String logUser(String email, String password) {
-    User u = dao.findUserByMail(email);
-
-    System.err.println("[AUTH] user e:"+email+" p:"+password+" u:"+u);
-
-    if(u == null) return null;
-
-    if(!u.getPassword().equals(password)) return null;
-
-    Key key = KeyGenerator.generateKey();
-    String token = Jwts.builder()
-      .setSubject(u.getId().toString())
-      .claim("id",u.getId())
-      .setIssuedAt(new Date())
-      .setExpiration(toDate(LocalDateTime.now().plusDays(1L)))
-      .signWith(SignatureAlgorithm.HS512, key)
-      .compact();
-
-    return token;
-  }
-
   @Override
   public boolean resetPassword(String email) {
     // TODO Auto-generated method stub
@@ -74,8 +55,9 @@ public class UserManager implements IUserManager {
     return false;
   }
 
-  private Date toDate(LocalDateTime localDateTime) {
-    return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
+  @Override
+  public User getUserByUsername(String username) {
+    return dao.findUserByUsername(username);
   }
   
 }
\ No newline at end of file
diff --git a/mozen/src/main/java/mozen/model/LoginMessage.java b/mozen/src/main/java/mozen/model/LoginMessage.java
index bea9e801af7edcee64d1866abff4611e996b5527..89d97549e933027a493a4db0c229d140231ec65e 100644
--- a/mozen/src/main/java/mozen/model/LoginMessage.java
+++ b/mozen/src/main/java/mozen/model/LoginMessage.java
@@ -5,7 +5,7 @@ import java.io.Serializable;
 public class LoginMessage implements Serializable {
   private static final long serialVersionUID = 1L;
 
-  private String email;
+  private String username;
 
   private String password;
 
@@ -13,17 +13,17 @@ public class LoginMessage implements Serializable {
   public LoginMessage() {
   }
 
-  public LoginMessage(String email, String password) {
-    this.email = email;
+  public LoginMessage(String username, String password) {
+    this.username = username;
     this.password = password;
   }
 
-  public String getEmail() {
-    return this.email;
+  public String getUsername() {
+    return this.username;
   }
 
-  public void setEmail(String email) {
-    this.email = email;
+  public void setUsername(String username) {
+    this.username = username;
   }
 
   public String getPassword() {
diff --git a/mozen/src/main/java/mozen/model/Model.java b/mozen/src/main/java/mozen/model/Model.java
index 9b673a53b2dd427f1fe9c433df4fe7551afd377c..8d0b907c20498391e71e973f26f738a7eb18a921 100644
--- a/mozen/src/main/java/mozen/model/Model.java
+++ b/mozen/src/main/java/mozen/model/Model.java
@@ -21,6 +21,8 @@ import javax.validation.constraints.Size;
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
 
+import org.springframework.format.annotation.DateTimeFormat;
+
 @Entity
 @Table
 public class Model implements Serializable{
@@ -46,6 +48,16 @@ public class Model implements Serializable{
   @Size(min = 0, max = 5000)
   private String longDescription;
 
+  @Basic
+	@DateTimeFormat(pattern = "yyyy-mm-dd")
+	@Column
+  private String added;
+  
+  @Basic
+	@DateTimeFormat(pattern = "yyyy-mm-dd")
+	@Column
+	private String lastModified;
+
   @Basic
 	@Column
   private int votes;
@@ -71,11 +83,13 @@ public class Model implements Serializable{
   public Model() {
   }
 
-  public Model(Long id, String name, String shortDescription, String longDescription, int votes, String filePath, User author, Set<Tag> tags, Set<CustomLayer> customLayers) {
+  public Model(Long id, String name, String shortDescription, String longDescription, String added, String lastModified, int votes, String filePath, User author, Set<Tag> tags, Set<CustomLayer> customLayers) {
     this.id = id;
     this.name = name;
     this.shortDescription = shortDescription;
     this.longDescription = longDescription;
+    this.added = added;
+    this.lastModified = lastModified;
     this.votes = votes;
     this.filePath = filePath;
     this.author = author;
@@ -83,7 +97,6 @@ public class Model implements Serializable{
     this.customLayers = customLayers;
   }
 
-
   public Long getId() {
     return this.id;
   }
@@ -116,6 +129,22 @@ public class Model implements Serializable{
     this.longDescription = longDescription;
   }
 
+  public String getAdded() {
+    return this.added;
+  }
+
+  public void setAdded(String added) {
+    this.added = added;
+  }
+
+  public String getLastModified() {
+    return this.lastModified;
+  }
+
+  public void setLastModified(String lastModified) {
+    this.lastModified = lastModified;
+  }
+
   public int getVotes() {
     return this.votes;
   }
@@ -155,6 +184,6 @@ public class Model implements Serializable{
 
   public void setCustomLayers(Set<CustomLayer> customLayers) {
     this.customLayers = customLayers;
-  }
+  }  
 
 }
\ No newline at end of file
diff --git a/mozen/src/main/java/mozen/model/SearchResult.java b/mozen/src/main/java/mozen/model/SearchResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..d8c81f519325d8eb8346f73830dcee891abc44a4
--- /dev/null
+++ b/mozen/src/main/java/mozen/model/SearchResult.java
@@ -0,0 +1,47 @@
+package mozen.model;
+
+import java.io.Serializable;
+import java.util.Collection;
+
+public class SearchResult implements Serializable {
+  private static final long serialVersionUID = 1L;
+
+  private int total;
+  private int page;
+  private Collection<Model> models;
+
+
+  public SearchResult() {
+  }
+
+  public SearchResult(int total, int page, Collection<Model> models) {
+    this.total = total;
+    this.page = page;
+    this.models = models;
+  }
+
+  public int getTotal() {
+    return this.total;
+  }
+
+  public void setTotal(int total) {
+    this.total = total;
+  }
+
+  public int getPage() {
+    return this.page;
+  }
+
+  public void setPage(int page) {
+    this.page = page;
+  }
+
+  public Collection<Model> getModels() {
+    return this.models;
+  }
+
+  public void setModels(Collection<Model> models) {
+    this.models = models;
+  }
+  
+}
\ No newline at end of file
diff --git a/mozen/src/main/java/mozen/model/SignupMessage.java b/mozen/src/main/java/mozen/model/SignupMessage.java
new file mode 100644
index 0000000000000000000000000000000000000000..816fc862a622bba7cd86bc7cea84d9c082b79fed
--- /dev/null
+++ b/mozen/src/main/java/mozen/model/SignupMessage.java
@@ -0,0 +1,62 @@
+package mozen.model;
+
+import java.io.Serializable;
+
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+import javax.validation.constraints.Size;
+
+public class SignupMessage implements Serializable {
+  private static final long serialVersionUID = 1L;
+  
+  @NotNull
+  @Size(min = 1, max = 30)
+  private String username;
+
+  @NotNull
+  @Size(min = 1, max = 60)
+  //@Pattern(regexp="(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#$%^&*-_=+])[a-zA-Z0-9!@#$%^&*-_=+](?=\\S+$).{8,35}")
+  private String password;
+  
+  @NotNull
+  @Size(min = 1, max = 30)
+  @Pattern(regexp="([a-z0-9])+([.]([a-z0-9])+)?@([a-z])+(([.]([a-z])+)?|([-]([a-z])+)?)+.([a-z]){2,}")
+  private String email;
+
+
+  public SignupMessage() {
+  }
+
+
+  public SignupMessage(String username, String password, String email) {
+    this.username = username;
+    this.password = password;
+    this.email = email;
+  }
+
+
+  public String getUsername() {
+    return this.username;
+  }
+
+  public void setUsername(String username) {
+    this.username = username;
+  }
+
+  public String getPassword() {
+    return this.password;
+  }
+
+  public void setPassword(String password) {
+    this.password = password;
+  }
+
+  public String getEmail() {
+    return this.email;
+  }
+
+  public void setEmail(String email) {
+    this.email = email;
+  }
+
+}
\ No newline at end of file
diff --git a/mozen/src/main/java/mozen/model/Tag.java b/mozen/src/main/java/mozen/model/Tag.java
index 03ca22b4f6d9450d46ab8a6efde3fdd99d1feaea..fb436b9efd80a64dfccf8f9ef7c512f54496491f 100644
--- a/mozen/src/main/java/mozen/model/Tag.java
+++ b/mozen/src/main/java/mozen/model/Tag.java
@@ -12,6 +12,7 @@ import javax.persistence.GeneratedValue;
 import javax.persistence.GenerationType;
 import javax.persistence.Id;
 import javax.persistence.ManyToMany;
+import javax.persistence.ManyToOne;
 import javax.persistence.Table;
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
@@ -26,8 +27,8 @@ public class Tag implements Serializable{
   private Long id;
 
   @Basic
-	@Column(nullable = false)
-  private String category;
+  @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
+  private TagCategory category;
   
   @Basic
 	@Column(nullable = false)
@@ -40,7 +41,7 @@ public class Tag implements Serializable{
   public Tag() {
   }
 
-  public Tag(Long id, String category, String name, Set<Model> models) {
+  public Tag(Long id, TagCategory category, String name, Set<Model> models) {
     this.id = id;
     this.category = category;
     this.name = name;
@@ -55,11 +56,12 @@ public class Tag implements Serializable{
     this.id = id;
   }
 
-  public String getCategory() {
+  @JsonIgnore
+  public TagCategory getCategory() {
     return this.category;
   }
 
-  public void setCategory(String category) {
+  public void setCategory(TagCategory category) {
     this.category = category;
   }
 
diff --git a/mozen/src/main/java/mozen/model/TagCategory.java b/mozen/src/main/java/mozen/model/TagCategory.java
new file mode 100644
index 0000000000000000000000000000000000000000..817426b5454656d4e9f9d55bd3239026cc8021f6
--- /dev/null
+++ b/mozen/src/main/java/mozen/model/TagCategory.java
@@ -0,0 +1,68 @@
+package mozen.model;
+
+import java.io.Serializable;
+import java.util.Set;
+
+import javax.persistence.Basic;
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+
+@Entity
+@Table
+public class TagCategory implements Serializable{
+  private static final long serialVersionUID = 1L;
+ 
+  @Id
+  @GeneratedValue(strategy = GenerationType.IDENTITY)
+  private Long id;
+
+  @Basic
+	@Column(nullable = false)
+  private String name;
+
+  @Basic 
+  @OneToMany(mappedBy = "category", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
+  private Set<Tag> tags;
+
+
+  public TagCategory() {
+  }
+
+  public TagCategory(Long id, String name, Set<Tag> tags) {
+    this.id = id;
+    this.name = name;
+    this.tags = tags;
+  }
+
+  public Long getId() {
+    return this.id;
+  }
+
+  public void setId(Long id) {
+    this.id = id;
+  }
+
+  public String getName() {
+    return this.name;
+  }
+
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  public Set<Tag> getTags() {
+    return this.tags;
+  }
+
+  public void setTags(Set<Tag> tags) {
+    this.tags = tags;
+  }
+  
+}
\ No newline at end of file
diff --git a/mozen/src/main/java/mozen/model/User.java b/mozen/src/main/java/mozen/model/User.java
index f4aa30a873c5f22898209f87e4fd0aea67750c0c..b8db2c721aaf0fbebc887f5d10ac60990c943410 100644
--- a/mozen/src/main/java/mozen/model/User.java
+++ b/mozen/src/main/java/mozen/model/User.java
@@ -34,6 +34,13 @@ public class User implements Serializable{
   @NotNull
   @Size(min = 1, max = 30)
   private String username;
+
+  @Basic
+  @Column(nullable = false)
+  @NotNull
+  @Size(min = 1, max = 60)
+  //@Pattern(regexp="(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#$%^&*-_=+])[a-zA-Z0-9!@#$%^&*-_=+](?=\\S+$).{8,35}")
+  private String password;
   
   @Basic
   @Column(nullable = false, unique = true)
@@ -45,9 +52,7 @@ public class User implements Serializable{
   @Basic
   @Column(nullable = false)
   @NotNull
-  @Size(min = 1, max = 60)
-  //@Pattern(regexp="(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#$%^&*-_=+])[a-zA-Z0-9!@#$%^&*-_=+](?=\\S+$).{8,35}")
-  private String password;
+  private String role;
   
   @Basic
   @OneToMany(mappedBy = "author", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@@ -57,15 +62,15 @@ public class User implements Serializable{
   public User() {
   }
 
-  public User(Long id, String username, String email, String password, Set<Model> models) {
+  public User(Long id, String username, String email, String password, String role, Set<Model> models) {
     this.id = id;
     this.username = username;
     this.email = email;
     this.password = password;
+    this.role = role;
     this.models = models;
   }
 
-
   public Long getId() {
     return this.id;
   }
@@ -82,14 +87,6 @@ public class User implements Serializable{
     this.username = username;
   }
 
-  public String getEmail() {
-    return this.email;
-  }
-
-  public void setEmail(String email) {
-    this.email = email;
-  }
-
   @JsonIgnore
   public String getPassword() {
     return this.password;
@@ -99,6 +96,14 @@ public class User implements Serializable{
     this.password = password;
   }
 
+  public String getEmail() {
+    return this.email;
+  }
+
+  public void setEmail(String email) {
+    this.email = email;
+  }
+
   @JsonIgnore
   public Set<Model> getModels() {
     return this.models;
@@ -107,5 +112,15 @@ public class User implements Serializable{
   public void setModels(Set<Model> models) {
     this.models = models;
   }
+
+  @JsonIgnore
+  public String getRole() {
+    return this.role;
+  }
+
+  public void setRole(String role) {
+    this.role = role;
+  }
+
   
 }
\ No newline at end of file
diff --git a/mozen/src/main/java/mozen/business/DatabaseFiller.java b/mozen/src/main/java/mozen/utils/DatabaseFiller.java
similarity index 81%
rename from mozen/src/main/java/mozen/business/DatabaseFiller.java
rename to mozen/src/main/java/mozen/utils/DatabaseFiller.java
index 802c26a3f9b6c6fb0d6abcd6c84547049866bb84..6754eac2bc8dc682e358bd5283b7404da5dc5f97 100644
--- a/mozen/src/main/java/mozen/business/DatabaseFiller.java
+++ b/mozen/src/main/java/mozen/utils/DatabaseFiller.java
@@ -1,4 +1,4 @@
-package mozen.business;
+package mozen.utils;
 
 import java.util.HashSet;
 import java.util.Set;
@@ -9,9 +9,12 @@ import org.springframework.context.event.EventListener;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import mozen.business.IModelDao;
+import mozen.business.IUserDao;
 import mozen.model.CustomLayer;
 import mozen.model.Model;
 import mozen.model.Tag;
+import mozen.model.TagCategory;
 import mozen.model.User;
 
 @Service
@@ -34,11 +37,13 @@ public class DatabaseFiller {
     u1.setEmail("user1@email.com");
     u1.setPassword("1234");
     u1.setUsername("user 1");
+    u1.setRole("DEFAULT");
 
     User u2 = new User();
     u2.setEmail("user2@email.com");
     u2.setPassword("1234");
     u2.setUsername("user 2");
+    u2.setRole("ADMIN");
 
     Model m1 = new Model();
     m1.setAuthor(u1);
@@ -46,14 +51,20 @@ public class DatabaseFiller {
     m1.setShortDescription("short description 1");
     m1.setLongDescription("# README \n model 1");
     m1.setVotes(0);
+    m1.setAdded("1990-05-30");
+    m1.setLastModified("2010-10-24");
 
     Set<Tag> m1tags = new HashSet<Tag>();
     Tag t1 = new Tag();
-    t1.setCategory("Layers");
+    TagCategory ca1 = new TagCategory();
+    ca1.setName("Layer");
+    t1.setCategory(ca1);
     t1.setName("Conv2D");
 
     Tag t2 = new Tag();
-    t2.setCategory("Architecture");
+    TagCategory ca2 = new TagCategory();
+    ca2.setName("Architecture");
+    t2.setCategory(ca2);
     t2.setName("VGG19");
 
     m1tags.add(t1);
diff --git a/mozen/src/main/java/mozen/web/ModelController.java b/mozen/src/main/java/mozen/web/ModelController.java
index 775846778bc61a9e893b902857cadbd3aba0433a..a9e58a06824dab8d57dad964877bb177c9a12e8a 100644
--- a/mozen/src/main/java/mozen/web/ModelController.java
+++ b/mozen/src/main/java/mozen/web/ModelController.java
@@ -14,7 +14,7 @@ import mozen.business.IModelManager;
 import mozen.business.IUserManager;
 import mozen.model.Model;
 import mozen.model.ResponseMessage;
-import mozen.model.Tag;
+import mozen.model.TagCategory;
 
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestParam;
@@ -22,7 +22,7 @@ import org.springframework.web.bind.annotation.RequestParam;
 
 
 @RestController
-@RequestMapping("/v1/models")
+@RequestMapping("/models")
 @CrossOrigin
 public class ModelController {
   @Autowired
@@ -64,7 +64,7 @@ public class ModelController {
   }
 
   @GetMapping("/tags")
-  public Collection<Tag> getTags() {
+  public Collection<TagCategory> getTags() {
     return modelManager.getTags();
   }
 }
\ No newline at end of file
diff --git a/mozen/src/main/java/mozen/web/SearchController.java b/mozen/src/main/java/mozen/web/SearchController.java
index c783314fe543a4fd11c74369ec2f8436561b9111..1a8db21145582e34151439ba95d9aaa1ee10f6c3 100644
--- a/mozen/src/main/java/mozen/web/SearchController.java
+++ b/mozen/src/main/java/mozen/web/SearchController.java
@@ -10,17 +10,17 @@ import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
 import mozen.business.IModelManager;
-import mozen.model.Model;
+import mozen.model.SearchResult;
 
 @RestController
-@RequestMapping("/v1/search")
+@RequestMapping("/search")
 @CrossOrigin
 public class SearchController {
   @Autowired
   IModelManager modelManager;
   
   @GetMapping("")
-  public Collection<Model> search(
+  public SearchResult search(
       @RequestParam(value = "name", required = false) String name,
       @RequestParam(value = "tag", required = false) Collection<String> tag,
       @RequestParam(value = "param", required = false) Integer param,
@@ -29,6 +29,10 @@ public class SearchController {
       @RequestParam(value = "sort", required = false) String sort
     ) 
   {
-    return modelManager.findModel(name);
+    SearchResult result = new SearchResult();
+    result.setModels(modelManager.findModel(name));
+    result.setTotal(result.getModels().size());
+    result.setPage(page);
+    return result;
   }
 }
\ No newline at end of file
diff --git a/mozen/src/main/java/mozen/web/UserController.java b/mozen/src/main/java/mozen/web/UserController.java
index 09f45a771e6acfc1657ff619e3f367863cccdbcd..f62dc80eefbdfd0f792c6818b0d2895bd9c81b1e 100644
--- a/mozen/src/main/java/mozen/web/UserController.java
+++ b/mozen/src/main/java/mozen/web/UserController.java
@@ -13,12 +13,12 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
 import mozen.business.IUserManager;
-import mozen.model.LoginMessage;
 import mozen.model.ResponseMessage;
+import mozen.model.SignupMessage;
 import mozen.model.User;
 
 @RestController
-@RequestMapping("/v1/user")
+@RequestMapping("/user")
 @CrossOrigin
 public class UserController {
   @Autowired
@@ -29,21 +29,12 @@ public class UserController {
     return new User();
   }
 
-  @PostMapping("")
-  public ResponseEntity<ResponseMessage> addUser(@RequestBody @Valid User user, BindingResult result) {
-    manager.addUser(user);
+  @PostMapping("/signup")
+  public ResponseEntity<ResponseMessage> addUser(@RequestBody @Valid SignupMessage message, BindingResult result) {
+    System.err.println("SIGNUP u:"+message.getUsername()+" e:"+message.getEmail()+" p:"+message.getPassword());
+    manager.addUser(message);
     ResponseMessage response = new ResponseMessage(false, "");
     return ResponseEntity.ok(response);
   }
 
-  @PostMapping("/auth")
-  public ResponseEntity<ResponseMessage> authUser(@RequestBody LoginMessage message) {
-    ResponseMessage response = new ResponseMessage(false, "");
-    String token = manager.logUser(message.getEmail(), message.getPassword());
-    
-    if(token == null) response.setError(true);
-    else response.setMessage(token);
-
-    return ResponseEntity.ok(response);
-  }
 }
\ No newline at end of file
diff --git a/mozen/src/main/java/mozen/web/VoteController.java b/mozen/src/main/java/mozen/web/VoteController.java
index 8b89807f3f22ed3755911433afe0b494d646aa3f..72f3f24fe10e7a66d258cafeb3b5d3d9fb562348 100644
--- a/mozen/src/main/java/mozen/web/VoteController.java
+++ b/mozen/src/main/java/mozen/web/VoteController.java
@@ -13,7 +13,7 @@ import mozen.business.IUserManager;
 import org.springframework.web.bind.annotation.RequestParam;
 
 @RestController
-@RequestMapping("/v1/vote")
+@RequestMapping("/vote")
 @CrossOrigin
 public class VoteController {
   @Autowired