diff --git a/app/server/server/pom.xml b/app/server/server/pom.xml new file mode 100644 index 0000000000..04045af41f --- /dev/null +++ b/app/server/server/pom.xml @@ -0,0 +1,70 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.1.3.RELEASE + + + com.mobtools + server + 0.0.1-SNAPSHOT + server + This is the API server for the Mobtools project + + + 11 + + + + + org.springframework.boot + spring-boot-starter-cache + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-webflux + + + + org.postgresql + postgresql + runtime + + + org.projectlombok + lombok + true + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.security + spring-security-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/app/server/server/src/main/java/com/mobtools/server/ServerApplication.java b/app/server/server/src/main/java/com/mobtools/server/ServerApplication.java new file mode 100644 index 0000000000..ac7a801d35 --- /dev/null +++ b/app/server/server/src/main/java/com/mobtools/server/ServerApplication.java @@ -0,0 +1,13 @@ +package com.mobtools.server; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ServerApplication { + + public static void main(String[] args) { + SpringApplication.run(ServerApplication.class, args); + } + +} diff --git a/app/server/server/src/main/java/com/mobtools/server/configurations/CommonConfig.java b/app/server/server/src/main/java/com/mobtools/server/configurations/CommonConfig.java new file mode 100644 index 0000000000..bd9d22c57e --- /dev/null +++ b/app/server/server/src/main/java/com/mobtools/server/configurations/CommonConfig.java @@ -0,0 +1,19 @@ +package com.mobtools.server.configurations; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +import reactor.core.scheduler.Scheduler; +import reactor.core.scheduler.Schedulers; + +@Configuration +@EnableJpaAuditing +public class CommonConfig { + + private String ELASTIC_THREAD_POOL_NAME = "mobtools-elastic-pool"; + + @Bean + public Scheduler scheduler() { + return Schedulers.newElastic(ELASTIC_THREAD_POOL_NAME); + } +} diff --git a/app/server/server/src/main/java/com/mobtools/server/configurations/SecurityConfig.java b/app/server/server/src/main/java/com/mobtools/server/configurations/SecurityConfig.java new file mode 100644 index 0000000000..3fe1409516 --- /dev/null +++ b/app/server/server/src/main/java/com/mobtools/server/configurations/SecurityConfig.java @@ -0,0 +1,41 @@ +package com.mobtools.server.configurations; + + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity; +import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; +import org.springframework.security.config.web.server.ServerHttpSecurity; +import org.springframework.security.web.server.SecurityWebFilterChain; + +@Configuration +@EnableWebFluxSecurity +@EnableReactiveMethodSecurity +public class SecurityConfig { + +// private final DaoAuthenticationManager reactiveAuthenticationManager; + +// private final SecurityContextRepository securityContextRepository; + +// @Autowired +// public SecurityConfig(DaoAuthenticationManager reactiveAuthenticationManager, +// SecurityContextRepository securityContextRepository) { +// this.reactiveAuthenticationManager = reactiveAuthenticationManager; +// this.securityContextRepository = securityContextRepository; +// } + + @Bean + public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) { + return http + .csrf().disable() + .formLogin().disable() + .httpBasic().disable() +// .authenticationManager(reactiveAuthenticationManager) +// .securityContextRepository(securityContextRepository) + .authorizeExchange() + .anyExchange().permitAll() + .and() + .logout().disable() + .build(); + } +} diff --git a/app/server/server/src/main/java/com/mobtools/server/constants/Url.java b/app/server/server/src/main/java/com/mobtools/server/constants/Url.java new file mode 100644 index 0000000000..3159a870b7 --- /dev/null +++ b/app/server/server/src/main/java/com/mobtools/server/constants/Url.java @@ -0,0 +1,7 @@ +package com.mobtools.server.constants; + +public interface Url { + String BASE_URL = "/api"; + String VERSION = "/v1"; + String WIDGET_URL = BASE_URL + VERSION + "/widgets"; +} diff --git a/app/server/server/src/main/java/com/mobtools/server/controllers/BaseController.java b/app/server/server/src/main/java/com/mobtools/server/controllers/BaseController.java new file mode 100644 index 0000000000..cbd5a8ff07 --- /dev/null +++ b/app/server/server/src/main/java/com/mobtools/server/controllers/BaseController.java @@ -0,0 +1,4 @@ +package com.mobtools.server.controllers; + +public abstract class BaseController { +} diff --git a/app/server/server/src/main/java/com/mobtools/server/controllers/WidgetController.java b/app/server/server/src/main/java/com/mobtools/server/controllers/WidgetController.java new file mode 100644 index 0000000000..0a4575300c --- /dev/null +++ b/app/server/server/src/main/java/com/mobtools/server/controllers/WidgetController.java @@ -0,0 +1,47 @@ +package com.mobtools.server.controllers; + +import com.mobtools.server.constants.Url; +import com.mobtools.server.domains.Widget; +import com.mobtools.server.dtos.ResponseDto; +import com.mobtools.server.services.WidgetService; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import javax.validation.Valid; + +@RestController +@RequestMapping(Url.WIDGET_URL) +@RequiredArgsConstructor +public class WidgetController extends BaseController { + + private final WidgetService widgetService; + + @PostMapping + @ResponseStatus(HttpStatus.CREATED) + public Mono> create(@Valid @RequestBody Widget widget) { + return widgetService.create(widget) + .map(createdWidget -> new ResponseDto<>(HttpStatus.CREATED.value(), createdWidget, null)); + } + + @GetMapping("") + public Flux> getAllWidgets() { + return widgetService.get() + .map(user -> new ResponseDto<>(HttpStatus.OK.value(), user, null)); + } + + @GetMapping("/{name}") + public Mono> getByName(@PathVariable String id) { + return widgetService.getByName(id) + .map(user -> new ResponseDto<>(HttpStatus.OK.value(), user, null)); + } + + @PutMapping("/{id}") + public Mono> getCureFitUser(@PathVariable Long id) { + return widgetService.update(id) + .map(cfUser -> new ResponseDto<>(HttpStatus.OK.value(), cfUser, null)); + } + +} diff --git a/app/server/server/src/main/java/com/mobtools/server/domains/BaseDomain.java b/app/server/server/src/main/java/com/mobtools/server/domains/BaseDomain.java new file mode 100644 index 0000000000..d25c5ee07e --- /dev/null +++ b/app/server/server/src/main/java/com/mobtools/server/domains/BaseDomain.java @@ -0,0 +1,45 @@ +package com.mobtools.server.domains; + +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.springframework.data.annotation.CreatedBy; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedBy; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import javax.persistence.*; +import java.io.Serializable; +import java.util.Date; + +@EntityListeners(AuditingEntityListener.class) +@MappedSuperclass +@Getter +@Setter +@ToString +public abstract class BaseDomain implements Serializable { + + private static final long serialVersionUID = 7459916000501322517L; + + @Temporal(TemporalType.TIMESTAMP) + @Column(nullable = false, updatable = false) + @CreatedDate + protected Date createdAt; + + @Temporal(TemporalType.TIMESTAMP) + @Column(nullable = false) + @LastModifiedDate + protected Date updatedAt; + + @Column + @CreatedBy + protected String createdBy; + + @Column + @LastModifiedBy + protected String modifiedBy; + + @Column(nullable = false) + protected Boolean deleted = false; +} diff --git a/app/server/server/src/main/java/com/mobtools/server/domains/PricingPlan.java b/app/server/server/src/main/java/com/mobtools/server/domains/PricingPlan.java new file mode 100644 index 0000000000..11ac68d2a1 --- /dev/null +++ b/app/server/server/src/main/java/com/mobtools/server/domains/PricingPlan.java @@ -0,0 +1,5 @@ +package com.mobtools.server.domains; + +public enum PricingPlan { + FREE, STARTUP, BUSINESS, ENTERPRISE +} diff --git a/app/server/server/src/main/java/com/mobtools/server/domains/Tenant.java b/app/server/server/src/main/java/com/mobtools/server/domains/Tenant.java new file mode 100644 index 0000000000..eab549f987 --- /dev/null +++ b/app/server/server/src/main/java/com/mobtools/server/domains/Tenant.java @@ -0,0 +1,29 @@ +package com.mobtools.server.domains; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +import javax.persistence.*; +import javax.validation.constraints.NotNull; + +@Entity +@Getter +@Setter +@ToString +@NoArgsConstructor +@SequenceGenerator(initialValue = 1, name = "tenant_gen", sequenceName = "tenant_gen") +public class Tenant extends BaseDomain { + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "tenant_gen") + @Column(nullable = false, updatable = false) + private Long id; + + private String domain; + + private String name; + + private String website; + +} diff --git a/app/server/server/src/main/java/com/mobtools/server/domains/User.java b/app/server/server/src/main/java/com/mobtools/server/domains/User.java new file mode 100644 index 0000000000..85c3dfb4af --- /dev/null +++ b/app/server/server/src/main/java/com/mobtools/server/domains/User.java @@ -0,0 +1,31 @@ +package com.mobtools.server.domains; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +import javax.persistence.*; +import javax.validation.constraints.NotNull; + +@Entity +// Specially adding the table name here because the keyword "User" is reserved in Postgres +@Table(name = "users") +@Getter +@Setter +@ToString +@NoArgsConstructor +@SequenceGenerator(initialValue = 1, name = "user_gen", sequenceName = "user_gen") +public class User extends BaseDomain { + + @Id + @Column(nullable = false) + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_gen") + private Long id; + + @Column + private String name; + + @Column + private String email; +} diff --git a/app/server/server/src/main/java/com/mobtools/server/domains/Widget.java b/app/server/server/src/main/java/com/mobtools/server/domains/Widget.java new file mode 100644 index 0000000000..dcf8ef3ff5 --- /dev/null +++ b/app/server/server/src/main/java/com/mobtools/server/domains/Widget.java @@ -0,0 +1,34 @@ +package com.mobtools.server.domains; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +import javax.persistence.*; +import javax.validation.constraints.NotNull; + +@Entity +@Getter +@Setter +@ToString +@NoArgsConstructor +@SequenceGenerator(initialValue = 1, name = "widget_gen", sequenceName = "widget_gen") +public class Widget extends BaseDomain { + + + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "widget_gen") + @Column(nullable = false, updatable = false) + private Long id; + + @Column + private String name; + + @Column + private WidgetType type; + + @Column + private PricingPlan pricingPlan; + +} diff --git a/app/server/server/src/main/java/com/mobtools/server/domains/WidgetType.java b/app/server/server/src/main/java/com/mobtools/server/domains/WidgetType.java new file mode 100644 index 0000000000..9888f7d4a8 --- /dev/null +++ b/app/server/server/src/main/java/com/mobtools/server/domains/WidgetType.java @@ -0,0 +1,5 @@ +package com.mobtools.server.domains; + +public enum WidgetType { + DB, DISPLAY +} diff --git a/app/server/server/src/main/java/com/mobtools/server/dtos/ResponseDto.java b/app/server/server/src/main/java/com/mobtools/server/dtos/ResponseDto.java new file mode 100644 index 0000000000..6e5ae2edcb --- /dev/null +++ b/app/server/server/src/main/java/com/mobtools/server/dtos/ResponseDto.java @@ -0,0 +1,21 @@ +package com.mobtools.server.dtos; + +import lombok.*; + +import java.io.Serializable; + +@Getter +@Setter +@ToString +@NoArgsConstructor +@AllArgsConstructor +public class ResponseDto implements Serializable { + + private static final long serialVersionUID = 8965011907233699993L; + + private int status; + + private T data; + + private String message; +} diff --git a/app/server/server/src/main/java/com/mobtools/server/repositories/BaseRepository.java b/app/server/server/src/main/java/com/mobtools/server/repositories/BaseRepository.java new file mode 100644 index 0000000000..540f84838f --- /dev/null +++ b/app/server/server/src/main/java/com/mobtools/server/repositories/BaseRepository.java @@ -0,0 +1,11 @@ +package com.mobtools.server.repositories; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.repository.NoRepositoryBean; + +import java.io.Serializable; + +@NoRepositoryBean +public interface BaseRepository extends JpaRepository { + +} diff --git a/app/server/server/src/main/java/com/mobtools/server/repositories/WidgetRepository.java b/app/server/server/src/main/java/com/mobtools/server/repositories/WidgetRepository.java new file mode 100644 index 0000000000..b95b24e6c6 --- /dev/null +++ b/app/server/server/src/main/java/com/mobtools/server/repositories/WidgetRepository.java @@ -0,0 +1,9 @@ +package com.mobtools.server.repositories; + +import com.mobtools.server.domains.Widget; +import org.springframework.stereotype.Repository; + +@Repository +public interface WidgetRepository extends BaseRepository { + +} diff --git a/app/server/server/src/main/java/com/mobtools/server/services/BaseService.java b/app/server/server/src/main/java/com/mobtools/server/services/BaseService.java new file mode 100644 index 0000000000..044ee0ff98 --- /dev/null +++ b/app/server/server/src/main/java/com/mobtools/server/services/BaseService.java @@ -0,0 +1,10 @@ +package com.mobtools.server.services; + +import lombok.RequiredArgsConstructor; +import reactor.core.scheduler.Scheduler; + +@RequiredArgsConstructor +public abstract class BaseService { + + final Scheduler scheduler; +} \ No newline at end of file diff --git a/app/server/server/src/main/java/com/mobtools/server/services/WidgetService.java b/app/server/server/src/main/java/com/mobtools/server/services/WidgetService.java new file mode 100644 index 0000000000..e501a16a3a --- /dev/null +++ b/app/server/server/src/main/java/com/mobtools/server/services/WidgetService.java @@ -0,0 +1,16 @@ +package com.mobtools.server.services; + +import com.mobtools.server.domains.Widget; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +public interface WidgetService { + + Mono getByName(String id); + + Flux get(); + + Mono create(Widget widget); + + Mono update(Long id); +} diff --git a/app/server/server/src/main/java/com/mobtools/server/services/WidgetServiceImpl.java b/app/server/server/src/main/java/com/mobtools/server/services/WidgetServiceImpl.java new file mode 100644 index 0000000000..8fa01a3eaf --- /dev/null +++ b/app/server/server/src/main/java/com/mobtools/server/services/WidgetServiceImpl.java @@ -0,0 +1,45 @@ +package com.mobtools.server.services; + +import com.mobtools.server.domains.Widget; +import com.mobtools.server.repositories.WidgetRepository; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import reactor.core.scheduler.Scheduler; + +@Service +@Slf4j +public class WidgetServiceImpl extends BaseService implements WidgetService { + + private WidgetRepository widgetRepository; + + @Autowired + public WidgetServiceImpl(Scheduler scheduler, WidgetRepository widgetRepository) { + super(scheduler); + this.widgetRepository = widgetRepository; + } + + @Override + public Mono getByName(String id) { + return null; + } + + @Override + public Flux get() { + return null; + } + + @Override + public Mono create(Widget widget) { + return Mono.fromCallable( + () -> widgetRepository.save(widget) + ).subscribeOn(this.scheduler); + } + + @Override + public Mono update(Long id) { + return null; + } +} diff --git a/app/server/server/src/main/resources/application.properties b/app/server/server/src/main/resources/application.properties new file mode 100644 index 0000000000..d3250adf5a --- /dev/null +++ b/app/server/server/src/main/resources/application.properties @@ -0,0 +1,16 @@ +# JDBC Properties +spring.datasource.url=jdbc:postgresql://localhost:5432/mobtoolsnew?useSSL=false +spring.datasource.username=postgres +spring.datasource.password=root +spring.datasource.hikari.pool-name=Hikari-Eval-Pool +spring.datasource.hikari.maximum-pool-size=16 + +# JPA Properties +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect +spring.jpa.hibernate.ddl-auto=update +spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults=false +spring.jpa.show-sql=true + +# Jackson Properties +spring.jackson.default-property-inclusion=non_null + diff --git a/app/server/server/src/test/java/com/mobtools/server/ServerApplicationTests.java b/app/server/server/src/test/java/com/mobtools/server/ServerApplicationTests.java new file mode 100644 index 0000000000..bc025ad53e --- /dev/null +++ b/app/server/server/src/test/java/com/mobtools/server/ServerApplicationTests.java @@ -0,0 +1,16 @@ +package com.mobtools.server; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class ServerApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/app/server/url/constants.go b/app/server/url/constants.go index 19d2f2529b..be9d171a3b 100644 --- a/app/server/url/constants.go +++ b/app/server/url/constants.go @@ -3,6 +3,7 @@ package url const ComponentURL = "/components" const QueryURL = "/query" const LoginURL = "/login" +const AccountURL = "/accounts" const AuthURL = "/auth/{provider}" const AuthCallbackURL = "/auth/{provider}/callback" const LogoutURL = "/logout/{provider}"