Commit f6413e42 authored by Lukas Fülling's avatar Lukas Fülling 💻

initial

parents
Pipeline #620 passed with stage
in 2 minutes and 13 seconds
### Bower ###
/libs
### npm ###
/node_modules
### System ###
*.DS_Store
*Thumbs.db
### Build ###
/*.zip
/dist
/docs
/server
/reports
/assets/css
/assets/js/*.min.js
/assets/js/*.map
### Dev ###
config.codekit
*.sublime-project
*.sublime-workspace
*.log
.idea
*.iml
target
### DB ###
data/**/*
log/**/*
\ No newline at end of file
image: jamesdbloom/docker-java8-maven
services:
- tutum/mongodb
variables:
MONGODB_PASS: abcD123
before_script:
- mvn clean
stages:
- build
job1:
stage: build
script:
- mvn clean install
only:
- master
processManagement:
fork: true
net:
bindIp: 127.0.0.1
port: 27017
storage:
dbPath: data/db
systemLog:
destination: file
path: "log/mongod.log"
logAppend: true
storage:
journal:
enabled: true
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>net.k40s</groupId>
<artifactId>supertrack</artifactId>
<packaging>war</packaging>
<version>1.0</version>
<name>supertrack</name>
<developers>
<developer>
<id>lfuelling</id>
<name>Lukas Fülling</name>
<email>lukas@k40s.net</email>
<url>http://lerk.io</url>
<organization>K40S</organization>
<organizationUrl>http://www.k40s.net</organizationUrl>
<roles>
<role>Frontend Developer</role>
<role>Backend Developer</role>
</roles>
<timezone>Europe/Berlin</timezone>
<properties>
<picUrl>http://lerk.io/assets/img/lerk.jpg</picUrl>
</properties>
</developer>
</developers>
<issueManagement>
<system>GitLab</system>
<url>https://mzulft.k40s.net/supertrack/api/issues/</url>
</issueManagement>
<scm>
<connection>scm:git:https://mzulft.k40s.net/supertrack/api.git</connection>
<developerConnection>scm:git:ssh://git@mzulft.k40s.net:supertrack/api.git</developerConnection>
<tag>HEAD</tag>
<url>https://mzulft.k40s.net/supertrack/api</url>
</scm>
<build>
<finalName>supertrack</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<inherited>true</inherited>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey</groupId>
<artifactId>jersey-bom</artifactId>
<version>${jersey.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
<!-- use the following artifactId if you don't need servlet 2.x compatibility -->
<!-- artifactId>jersey-container-servlet</artifactId -->
</dependency>
<!-- mongoDB -->
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>2.13.2</version>
</dependency>
<!-- Joda-Time for better time and date handling -->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.3</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-servlet-api</artifactId>
<version>8.0.15</version>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts-core</artifactId>
<version>1.3.8</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.2.1.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-web</artifactId>
<version>2.4.1</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<properties>
<jersey.version>2.21</jersey.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
package net.k40s.supertrack;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientURI;
import net.k40s.supertrack.util.OutputExclusionStrategy;
/**
* @author Nicolai S&uuml;per (nico@k40s.net)
* @author Lukas F&uuml;lling (lukas@k40s.net)
*/
public class DatabaseHandler {
/**
* The Output GSONBuilder doesn't serialize the passwordHash and the token.
*
* @return The output GSONBuilder
* @see OutputExclusionStrategy
*/
public static Gson getOutputGson() {
return new GsonBuilder().setExclusionStrategies(new OutputExclusionStrategy()).create();
}
/**
* The DBGSONBuilder serializes all fields including the token and the password.
*
* @return The DB GSON Builder
*/
public static Gson getDBGson() {
return new GsonBuilder().create();
}
/**
* This URI allows us to connect to the database with user credentials.
*/
private static String DB_URI = "mongodb://" + getDbUri() + ":27017"; // TODO make this more dynamic
private static String getDbUri() {
String addr = System.getenv("DATABASE_PORT_27017_TCP_ADDR");
if(addr != null) {
return addr;
}
return "localhost";
}
public static DBCollection getCollection(String collectionName) {
MongoClient mongoClient;
DB db;
DBCollection collection = null;
try {
mongoClient = new MongoClient(new MongoClientURI(DB_URI));
db = mongoClient.getDB("supertrack");
collection = db.getCollection(collectionName);
} catch (Exception e) {
e.printStackTrace(); // TODO replace with advanced logging method
}
return collection;
}
// May not be needed because getCollection() does well too
public static DB getDatabase() {
MongoClient mongoClient;
DB db = null;
try {
mongoClient = new MongoClient(new MongoClientURI(DB_URI));
db = mongoClient.getDB("supertrack");
} catch (Exception e) {
e.printStackTrace(); // TODO replace
}
return db;
}
public static DB getDatabase(String DBName) {
MongoClient mongoClient;
DB db = null;
try {
mongoClient = new MongoClient(new MongoClientURI(DB_URI));
db = mongoClient.getDB(DBName);
} catch (Exception e) {
e.printStackTrace(); // TODO replace
}
return db;
}
}
package net.k40s.supertrack;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
import java.io.*;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
/**
* @author Nicolai S&uuml;per (nico@k40s.net)
*/
@Provider
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public final class GsonMessageBodyHandler implements MessageBodyWriter<Object>, MessageBodyReader<Object> {
private Gson gson;
private Gson getGson() {
if (gson == null) {
final GsonBuilder gsonBuilder = new GsonBuilder();
gson = gsonBuilder.create();
}
return gson;
}
@Override
public boolean isReadable(Class<?> type, Type genericType,
java.lang.annotation.Annotation[] annotations, MediaType mediaType) {
return true;
}
@Override
public Object readFrom(Class<Object> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException {
try (InputStreamReader streamReader = new InputStreamReader(entityStream, "UTF-8")) {
Type jsonType;
if (type.equals(genericType)) {
jsonType = type;
} else {
jsonType = genericType;
}
return getGson().fromJson(streamReader, jsonType);
}
}
@Override
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
return true;
}
@Override
public long getSize(Object object, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
return -1;
}
@Override
public void writeTo(Object object, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException {
try (OutputStreamWriter writer = new OutputStreamWriter(entityStream, "UTF-8")) {
Type jsonType;
if (type.equals(genericType)) {
jsonType = type;
} else {
jsonType = genericType;
}
getGson().toJson(object, jsonType, writer);
}
}
}
\ No newline at end of file
package net.k40s.supertrack.exceptions;
import java.util.Random;
/**
* This Exception is thrown when supertrack can't even.
*
* @author Lukas F&uuml;lling (lukas@k40s.net)
* @see <a href="http://de.urbandictionary.com/define.php?term=Can%27t+even">Urban Dictionary ("can't even")</a>
*/
public class CantEvenException extends Exception {
String message;
public CantEvenException() {
}
public CantEvenException(String message) {
this.message = randomizeCase(message);
}
public CantEvenException(String message, Throwable cause) {
super(cause);
this.message = randomizeCase(message);
}
@Override
public String getMessage() {
return randomizeCase(message);
}
/**
* Randomizes upper- and lowercase in a string.
*
* @param str the string you want to be randomized
* @return your randomized string
*/
public String randomizeCase(String str) {
Random rnd = new Random();
StringBuilder sb = new StringBuilder(str.length());
for (char c : str.toCharArray())
sb.append(rnd.nextBoolean()
? Character.toLowerCase(c)
: Character.toUpperCase(c));
return sb.toString();
}
}
package net.k40s.supertrack.exceptions;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
/**
* @author Nicolai S&uuml;per (nico@k40s.net)
*/
public class GeneralException extends WebApplicationException {
private static final Logger LOGGER = LogManager.getLogger(GeneralException.class);
public GeneralException() {
this("The program has encountered a general or unknown error."); // TODO change to something more... self-explaining.
LOGGER.error(this);
}
public GeneralException(String msg) {
super(Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(msg).type(MediaType.APPLICATION_JSON)
.build());
LOGGER.error(msg);
}
}
package net.k40s.supertrack.exceptions;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
/**
* @author Lukas F&uuml;lling (lukas@k40s.net)
*/
public class InconsistentDataException extends WebApplicationException {
private static final Logger LOGGER = LogManager.getLogger(InconsistentDataException.class);
public InconsistentDataException(String message) {
super(Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(message).type(MediaType.APPLICATION_JSON)
.build());
LOGGER.error(message, this);
}
}
package net.k40s.supertrack.objects.external;
import net.k40s.supertrack.objects.internal.User;
import org.joda.time.DateTime;
/**
* @author Lukas F&uuml;lling (lukas@k40s.net)
*/
public class CommentOut {
public String id;
public String content;
public User author;
public String timestamp;
public CommentOut(String id, String content, User author, String timestamp) {
this.id = id;
this.content = content;
this.author = author;
this.timestamp = timestamp;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public User getAuthor() {
return author;
}
public void setAuthor(User author) {
this.author = author;
}
public String getTimestamp() {
return timestamp;
}
public void setTimestamp(String timestamp) {
this.timestamp = timestamp;
}
}
package net.k40s.supertrack.objects.external;
import com.google.gson.annotations.SerializedName;
import net.k40s.supertrack.objects.internal.Comment;
import net.k40s.supertrack.objects.internal.User;
import java.util.ArrayList;
/**
* @author Lukas F&uuml;lling (lukas@k40s.net)
*/
public class IssueOut {
@SerializedName("id")
public String ID;
public String title, description, prefix;
public User creator, assignee; // assignee & creator are just IDs in internal object
public boolean closed = false; // Issue will be created with status=open per default
public ArrayList<CommentOut> commentList = new ArrayList<>();
public String internalID;
public ArrayList<String> labels;
public boolean editable = false;
public IssueOut(String ID, String title, String description, String prefix, User creator, User assignee, boolean closed, ArrayList<CommentOut> commentList, String internalID, ArrayList<String> labels) {
this.ID = ID;
this.title = title;
this.description = description;
this.prefix = prefix;
this.creator = creator;
this.assignee = assignee;
this.closed = closed;
this.commentList = commentList;
this.internalID = internalID;
this.labels = labels;
}
public boolean isEditable() {
return editable;
}
public void setEditable(boolean editable) {
this.editable = editable;
}
public ArrayList<String> getLabels() {
return labels;
}
public void setLabels(ArrayList<String> labels) {
this.labels = labels;
}
public String getInternalID() {
return internalID;
}
public void setInternalID(String internalID) {
this.internalID = internalID;
}
public ArrayList<CommentOut> getCommentList() {
return commentList;
}
public void setCommentList(ArrayList<CommentOut> commentList) {
this.commentList = commentList;
}
public String getID() {
return ID;
}
public void setID(String ID) {
this.ID = ID;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public User getCreator() {
return creator;
}
public void setCreator(User creator) {
this.creator = creator;
}
public boolean isClosed() {
return closed;
}
public void setClosed(boolean closed) {
this.closed = closed;
}
public User getAssignee() {
return assignee;
}
public void setAssignee(User assignee) {
this.assignee = assignee;