diff --git a/.codeclimate.yml b/.codeclimate.yml index 1f18975..54a7f30 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -1,5 +1,17 @@ --- engines: + csslint: + enabled: true + duplication: + enabled: true + config: + languages: + - ruby + - javascript + - python + - php + eslint: + enabled: true fixme: enabled: true gofmt: @@ -8,5 +20,16 @@ engines: enabled: true ratings: paths: - - "api/*.go" -exclude_paths: [] + - "**.css" + - "**.inc" + - "**.js" + - "**.jsx" + - "**.module" + - "**.php" + - "**.py" + - "**.rb" + - "**.go" +exclude_paths: + - github.com + - golang.org + - integration/node_modules diff --git a/.csslintrc b/.csslintrc new file mode 100644 index 0000000..aacba95 --- /dev/null +++ b/.csslintrc @@ -0,0 +1,2 @@ +--exclude-exts=.min.css +--ignore=adjoining-classes,box-model,ids,order-alphabetical,unqualified-attributes diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..96212a3 --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +**/*{.,-}min.js diff --git a/.eslintrc.yml b/.eslintrc.yml new file mode 100644 index 0000000..a6a0ce9 --- /dev/null +++ b/.eslintrc.yml @@ -0,0 +1,277 @@ +--- +parserOptions: + sourceType: module + ecmaFeatures: + jsx: true + +env: + amd: true + browser: true + es6: true + jquery: true + node: true + +# http://eslint.org/docs/rules/ +rules: + # Possible Errors + no-await-in-loop: off + no-cond-assign: error + no-console: off + no-constant-condition: error + no-control-regex: error + no-debugger: error + no-dupe-args: error + no-dupe-keys: error + no-duplicate-case: error + no-empty-character-class: error + no-empty: error + no-ex-assign: error + no-extra-boolean-cast: error + no-extra-parens: off + no-extra-semi: error + no-func-assign: error + no-inner-declarations: + - error + - functions + no-invalid-regexp: error + no-irregular-whitespace: error + no-negated-in-lhs: error + no-obj-calls: error + no-prototype-builtins: off + no-regex-spaces: error + no-sparse-arrays: error + no-template-curly-in-string: off + no-unexpected-multiline: error + no-unreachable: error + no-unsafe-finally: off + no-unsafe-negation: off + use-isnan: error + valid-jsdoc: off + valid-typeof: error + + # Best Practices + accessor-pairs: error + array-callback-return: off + block-scoped-var: off + class-methods-use-this: off + complexity: + - error + - 6 + consistent-return: off + curly: off + default-case: off + dot-location: off + dot-notation: off + eqeqeq: error + guard-for-in: error + no-alert: error + no-caller: error + no-case-declarations: error + no-div-regex: error + no-else-return: off + no-empty-function: off + no-empty-pattern: error + no-eq-null: error + no-eval: error + no-extend-native: error + no-extra-bind: error + no-extra-label: off + no-fallthrough: error + no-floating-decimal: off + no-global-assign: off + no-implicit-coercion: off + no-implied-eval: error + no-invalid-this: off + no-iterator: error + no-labels: + - error + - allowLoop: true + allowSwitch: true + no-lone-blocks: error + no-loop-func: error + no-magic-number: off + no-multi-spaces: off + no-multi-str: off + no-native-reassign: error + no-new-func: error + no-new-wrappers: error + no-new: error + no-octal-escape: error + no-octal: error + no-param-reassign: off + no-proto: error + no-redeclare: error + no-restricted-properties: off + no-return-assign: error + no-return-await: off + no-script-url: error + no-self-assign: off + no-self-compare: error + no-sequences: off + no-throw-literal: off + no-unmodified-loop-condition: off + no-unused-expressions: error + no-unused-labels: off + no-useless-call: error + no-useless-concat: error + no-useless-escape: off + no-useless-return: off + no-void: error + no-warning-comments: off + no-with: error + prefer-promise-reject-errors: off + radix: error + require-await: off + vars-on-top: off + wrap-iife: error + yoda: off + + # Strict + strict: off + + # Variables + init-declarations: off + no-catch-shadow: error + no-delete-var: error + no-label-var: error + no-restricted-globals: off + no-shadow-restricted-names: error + no-shadow: off + no-undef-init: error + no-undef: off + no-undefined: off + no-unused-vars: off + no-use-before-define: off + + # Node.js and CommonJS + callback-return: error + global-require: error + handle-callback-err: error + no-mixed-requires: off + no-new-require: off + no-path-concat: error + no-process-env: off + no-process-exit: error + no-restricted-modules: off + no-sync: off + + # Stylistic Issues + array-bracket-spacing: off + block-spacing: off + brace-style: off + camelcase: off + capitalized-comments: off + comma-dangle: + - error + - never + comma-spacing: off + comma-style: off + computed-property-spacing: off + consistent-this: off + eol-last: off + func-call-spacing: off + func-name-matching: off + func-names: off + func-style: off + id-length: off + id-match: off + indent: off + jsx-quotes: off + key-spacing: off + keyword-spacing: off + line-comment-position: off + linebreak-style: off + lines-around-comment: off + lines-around-directive: off + max-depth: off + max-len: off + max-nested-callbacks: off + max-params: off + max-statements-per-line: off + max-statements: + - error + - 30 + multiline-ternary: off + new-cap: off + new-parens: off + newline-after-var: off + newline-before-return: off + newline-per-chained-call: off + no-array-constructor: off + no-bitwise: off + no-continue: off + no-inline-comments: off + no-lonely-if: off + no-mixed-operators: off + no-mixed-spaces-and-tabs: off + no-multi-assign: off + no-multiple-empty-lines: off + no-negated-condition: off + no-nested-ternary: off + no-new-object: off + no-plusplus: off + no-restricted-syntax: off + no-spaced-func: off + no-tabs: off + no-ternary: off + no-trailing-spaces: off + no-underscore-dangle: off + no-unneeded-ternary: off + object-curly-newline: off + object-curly-spacing: off + object-property-newline: off + one-var-declaration-per-line: off + one-var: off + operator-assignment: off + operator-linebreak: off + padded-blocks: off + quote-props: off + quotes: off + require-jsdoc: off + semi-spacing: off + semi: off + sort-keys: off + sort-vars: off + space-before-blocks: off + space-before-function-paren: off + space-in-parens: off + space-infix-ops: off + space-unary-ops: off + spaced-comment: off + template-tag-spacing: off + unicode-bom: off + wrap-regex: off + + # ECMAScript 6 + arrow-body-style: off + arrow-parens: off + arrow-spacing: off + constructor-super: off + generator-star-spacing: off + no-class-assign: off + no-confusing-arrow: off + no-const-assign: off + no-dupe-class-members: off + no-duplicate-imports: off + no-new-symbol: off + no-restricted-imports: off + no-this-before-super: off + no-useless-computed-key: off + no-useless-constructor: off + no-useless-rename: off + no-var: off + object-shorthand: off + prefer-arrow-callback: off + prefer-const: off + prefer-destructuring: off + prefer-numeric-literals: off + prefer-rest-params: off + prefer-reflect: off + prefer-spread: off + prefer-template: off + require-yield: off + rest-spread-spacing: off + sort-imports: off + symbol-description: off + template-curly-spacing: off + yield-star-spacing: off diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6203a08 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.env +github.com +golang.org +integration/node_modules diff --git a/Dockerfile b/Dockerfile index 5c77e03..750f51f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,12 +1,13 @@ FROM golang:1.8 as build WORKDIR /go/src ENV CGO_ENABLED=0 -ENV GO_PATH=/go/src -RUN go get github.com/gorilla/mux -COPY api /go/src -RUN go build -a --installsuffix cgo --ldflags=-s -o bigdata4all +ENV GO_PATH=/go +COPY api /go/src/api +RUN cd api && go get -v +RUN cd api && go build -a -v --installsuffix cgo --ldflags=-s -o bigdata4all FROM scratch -COPY --from=build /go/src/bigdata4all / +COPY --from=build /go/src/api/bigdata4all / +COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt ENTRYPOINT ["/bigdata4all"] EXPOSE 80 diff --git a/api/api.go b/api/api.go index 3a359dc..802e0ed 100644 --- a/api/api.go +++ b/api/api.go @@ -1,15 +1,34 @@ package main import ( + "encoding/json" "flag" "fmt" + "github.com/dgrijalva/jwt-go" + "github.com/go-redis/redis" "github.com/gorilla/mux" + "github.com/gorilla/securecookie" + "golang.org/x/crypto/bcrypt" + "io/ioutil" "log" "net/http" "os" + "time" ) +type jsonUser struct { + Email string `json:"email"` + Password string `json:"password"` +} + +type basicResponse struct { + Result string `json:"result"` + Msg string `json:"msg"` +} + var port string +var secretKey string +var redisDB *redis.Client func init() { flag.StringVar(&port, "port", "80", "give me a port number") @@ -17,15 +36,198 @@ func init() { func main() { flag.Parse() + + // Init DB + redisDB = redis.NewClient(&redis.Options{ + Addr: "redis:6379", + Password: "", + DB: 0, + }) + + // Secret + secretKey = string(securecookie.GenerateRandomKey(32)) + + // Mux Router r := mux.NewRouter() + r.HandleFunc("/user/register", handleUserRegister).Methods("Post") + r.HandleFunc("/user/auth", handleUserAuth).Methods("Post") r.HandleFunc("/health", health) + r.HandleFunc("/data", handleData).Methods("Post") r.HandleFunc("/", health) http.Handle("/", r) + + // Start Http fmt.Println("Starting up on port " + port) log.Fatal(http.ListenAndServe(":"+port, nil)) } func health(w http.ResponseWriter, req *http.Request) { hostname, _ := os.Hostname() + w.Header().Set("Access-Control-Allow-Origin", "*") fmt.Fprintln(w, "Hostname:", hostname) } + +func handleUserRegister(w http.ResponseWriter, req *http.Request) { + bodyb, _ := ioutil.ReadAll(req.Body) + var user jsonUser + _ = json.Unmarshal(bodyb, &user) + + var response basicResponse + + // Verify user + _, err := redisDB.Get("user:" + user.Email).Result() + if err == redis.Nil { + // User not present in DB + token := randStringBytesMaskImprSrc(64) + // Insert redis + err = redisDB.Set("user:"+user.Email, token, 0).Err() + if err != nil { + panic(err) + } + hash, err := bcrypt.GenerateFromPassword([]byte(user.Password), bcrypt.DefaultCost) + if err != nil { + panic(err) + } + err = redisDB.Set("user:"+user.Email+":password", hash, 0).Err() + if err != nil { + panic(err) + } + // Send email + sendMailValidator(user.Email, token) + // Set response + response = basicResponse{ + Result: "success", + Msg: "You must validate your account, check your emails", + } + } else if err != nil { + panic(err) + } else { + // User already present in DB + response = basicResponse{ + Result: "failure", + Msg: "User already exists in database", + } + } + + // Send response + jsonResponse, err := json.Marshal(response) + if err != nil { + log.Fatalln(err) + } + w.Header().Set("Access-Control-Allow-Origin", "*") + fmt.Fprintln(w, string(jsonResponse)) +} + +func handleData(w http.ResponseWriter, req *http.Request) { + var response basicResponse + // Here we just verify that the user is authenticated + reqToken := req.Header.Get("X-Bigdata4all-Token") + token, err := jwt.Parse(reqToken, func(t *jwt.Token) (interface{}, error) { + return []byte(secretKey), nil + }) + if err == nil && token.Valid { + response = basicResponse{ + Result: "success", + Msg: "Valid token", + } + } else { + response = basicResponse{ + Result: "failure", + Msg: "Invalid token", + } + } + // Print response + jsonResponse, err := json.Marshal(response) + if err != nil { + log.Fatalln(err) + } + w.Header().Set("Access-Control-Allow-Origin", "*") + fmt.Fprintln(w, string(jsonResponse)) +} + +func handleUserAuth(w http.ResponseWriter, req *http.Request) { + var response basicResponse + + // If token, refresh it and send response + reqToken := req.Header.Get("X-Bigdata4all-Token") + if reqToken != "" { + token, err := jwt.Parse(reqToken, func(t *jwt.Token) (interface{}, error) { + return []byte(secretKey), nil + }) + if err == nil && token.Valid { + email := token.Claims.(jwt.MapClaims)["user"] + // Create JWT token + token = jwt.New(jwt.GetSigningMethod("HS256")) + claims := make(jwt.MapClaims) + claims["user"] = email + claims["exp"] = time.Now().Add(time.Minute * 3600).Unix() + token.Claims = claims + tokenString, err := token.SignedString([]byte(secretKey)) + if err != nil { + panic(err) + } + w.Header().Set("X-Bigdata4all-Token", tokenString) + response = basicResponse{ + Result: "success", + Msg: "Feel free to use token", + } + + } else { + response = basicResponse{ + Result: "failure", + Msg: "Invalid token", + } + } + + } else { + + bodyb, _ := ioutil.ReadAll(req.Body) + var user jsonUser + _ = json.Unmarshal(bodyb, &user) + + hash, err := redisDB.Get("user:" + user.Email + ":password").Result() + if err == redis.Nil { + // user doesn't exists + response = basicResponse{ + Result: "failure", + Msg: "Invalid credentials", + } + } else if err != nil { + panic(err) + } else { + // user exists, check password + if err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(user.Password)); err != nil { + // Bad password + response = basicResponse{ + Result: "failure", + Msg: "Invalid credentials", + } + } else { + // Good password + // Create JWT token + token := jwt.New(jwt.GetSigningMethod("HS256")) + claims := make(jwt.MapClaims) + claims["user"] = user.Email + claims["exp"] = time.Now().Add(time.Minute * 3600).Unix() + token.Claims = claims + tokenString, err := token.SignedString([]byte(secretKey)) + if err != nil { + panic(err) + } + w.Header().Set("X-Bigdata4all-Token", tokenString) + response = basicResponse{ + Result: "success", + Msg: "Feel free to use token", + } + } + } + } + + // Send response + jsonResponse, err := json.Marshal(response) + if err != nil { + log.Fatalln(err) + } + w.Header().Set("Access-Control-Allow-Origin", "*") + fmt.Fprintln(w, string(jsonResponse)) +} diff --git a/api/utils.go b/api/utils.go new file mode 100644 index 0000000..5fa48ce --- /dev/null +++ b/api/utils.go @@ -0,0 +1,57 @@ +package main + +import ( + "log" + "math/rand" + "net/smtp" + "os" + "time" +) + +const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" +const ( + letterIdxBits = 6 // 6 bits to represent a letter index + letterIdxMask = 1<= 0; { + if remain == 0 { + cache, remain = src.Int63(), letterIdxMax + } + if idx := int(cache & letterIdxMask); idx < len(letterBytes) { + b[i] = letterBytes[idx] + i-- + } + cache >>= letterIdxBits + remain-- + } + + return string(b) +} + +func sendMailValidator(to string, token string) { + user := os.Getenv("SMTP_USER") + pass := os.Getenv("SMTP_PASSWORD") + from := "contact@bigdata4all.io" + body := token + + msg := "From: " + from + "\n" + + "To: " + to + "\n" + + "Subject: Hello there\n\n" + + body + + err := smtp.SendMail(os.Getenv("SMTP_SERVER")+":"+os.Getenv("SMTP_PORT"), + smtp.PlainAuth("", user, pass, os.Getenv("SMTP_SERVER")), + from, []string{to}, []byte(msg)) + + if err != nil { + log.Printf("smtp error: %s", err) + return + } +} diff --git a/api/utils_test.go b/api/utils_test.go new file mode 100644 index 0000000..2635d67 --- /dev/null +++ b/api/utils_test.go @@ -0,0 +1,12 @@ +package main + +import ( + "testing" +) + +func TestRandStringBytesMaskImprSrc(t *testing.T) { + str := randStringBytesMaskImprSrc(64) + if len(str) != 64 { + t.Fatalf("randStringBytesMaskImprSrc(%d) == %d, want %d", 64, len(str), 64) + } +} diff --git a/codefresh.yml b/codefresh.yml index 77ff948..2b2844a 100644 --- a/codefresh.yml +++ b/codefresh.yml @@ -2,18 +2,48 @@ version: '1.0' steps: + unittest: + image: golang:1.8 + commands: + # Need to have the source in the correct GOPATH folder - let's do that + - mkdir -p /go/src/github.com/${{CF_REPO_OWNER}} + - ln -s /codefresh/volume/${{CF_REPO_NAME}} /go/src/github.com/${{CF_REPO_OWNER}}/${{CF_REPO_NAME}} + # Install pre-requisites and execute tests + - cd /go/src/github.com/${{CF_REPO_OWNER}}/${{CF_REPO_NAME}}/api && go get + - cd /go/src/github.com/${{CF_REPO_OWNER}}/${{CF_REPO_NAME}}/api && go test -v -coverprofile=coverage.txt -covermode=atomic + #- curl -s https://codecov.io/bash > codecov + #- bash codecov -t ${{CODECOV_TOKEN}} + build: type: build image_name: ${{CF_REPO_OWNER}}/${{CF_REPO_NAME}} + tag: ${{CF_BRANCH_TAG_NORMALIZED}} + + buildinttest: + type: build + image_name: ${{CF_REPO_OWNER}}/${{CF_REPO_NAME}} + dockerfile: integration/Dockerfile + tag: ${{CF_BRANCH_TAG_NORMALIZED}}-inttest + + inttest: + type: composition + composition: + version: '2' + services: + api: + image: ${{build}} + redis: + image: redis:latest + composition_candidates: + test_service: + image: ${{buildinttest}} + command: npm test push: type: push candidate: ${{build}} registry: dockerhub - when: - branch: - only: - - master + tag: ${{CF_BRANCH_TAG_NORMALIZED}} deploy: type: launch-composition diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..9e6394f --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,13 @@ +version: "3" +services: + api: + image: wtfcoderz/bigdata4all + ports: + - 10000:80 + environment: + - SMTP_SERVER=$SMTP_SERVER + - SMTP_PORT=$SMTP_PORT + - SMTP_USER=$SMTP_USER + - SMTP_PASSWORD=$SMTP_PASSWORD + redis: + image: redis diff --git a/integration/Dockerfile b/integration/Dockerfile new file mode 100644 index 0000000..ee7a699 --- /dev/null +++ b/integration/Dockerfile @@ -0,0 +1,4 @@ +FROM node:latest +COPY integration /usr/src +WORKDIR /usr/src +RUN npm install diff --git a/integration/package-lock.json b/integration/package-lock.json new file mode 100644 index 0000000..9f1f4cf --- /dev/null +++ b/integration/package-lock.json @@ -0,0 +1,512 @@ +{ + "name": "bigdata4all_test", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "assertion-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.2.tgz", + "integrity": "sha1-E8pRXYYgbaC6xm6DTdOX2HWBCUw=" + }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "browser-stdout": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", + "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=" + }, + "chai": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.1.0.tgz", + "integrity": "sha1-MxoDkbVcOvh0CunDt0WLwcOAXm0=", + "requires": { + "assertion-error": "1.0.2", + "check-error": "1.0.2", + "deep-eql": "2.0.2", + "get-func-name": "2.0.0", + "pathval": "1.1.0", + "type-detect": "4.0.3" + } + }, + "chai-http": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chai-http/-/chai-http-3.0.0.tgz", + "integrity": "sha1-VGDYA24fGhKwtbXL1Snm3B0x60s=", + "requires": { + "cookiejar": "2.0.6", + "is-ip": "1.0.0", + "methods": "1.1.2", + "qs": "6.5.0", + "superagent": "2.3.0" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } + } + }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=" + }, + "combined-stream": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "requires": { + "delayed-stream": "1.0.0" + } + }, + "commander": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "requires": { + "graceful-readlink": "1.0.1" + } + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "cookiejar": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.0.6.tgz", + "integrity": "sha1-Cr81atANHFohnYjURRgEbdAmrP4=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "debug": { + "version": "2.6.8", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "requires": { + "ms": "2.0.0" + } + }, + "deep-eql": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-2.0.2.tgz", + "integrity": "sha1-sbrAblbwp2d3aG1Qyf63XC7XZ5o=", + "requires": { + "type-detect": "3.0.0" + }, + "dependencies": { + "type-detect": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-3.0.0.tgz", + "integrity": "sha1-RtDMhVOrt7E6NSsNbeov1Y8tm1U=" + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "diff": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", + "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" + }, + "form-data": { + "version": "1.0.0-rc4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-1.0.0-rc4.tgz", + "integrity": "sha1-BaxrwiIntD5EYfSIFhVUaZ1Pi14=", + "requires": { + "async": "1.5.2", + "combined-stream": "1.0.5", + "mime-types": "2.1.16" + } + }, + "formidable": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.1.1.tgz", + "integrity": "sha1-lriIb3w8NQi5Mta9cMTTqI818ak=" + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=" + }, + "glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", + "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" + }, + "growl": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", + "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=" + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ip-regex": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-1.0.3.tgz", + "integrity": "sha1-3FiQdvZZ9BnCIgOaMzFvHHOH7/0=" + }, + "is-ip": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-ip/-/is-ip-1.0.0.tgz", + "integrity": "sha1-K7aVn3l8zW+f3IEnWLy8h8TFkHQ=", + "requires": { + "ip-regex": "1.0.3" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "json3": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", + "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=" + }, + "lodash._baseassign": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", + "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", + "requires": { + "lodash._basecopy": "3.0.1", + "lodash.keys": "3.1.2" + } + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=" + }, + "lodash._basecreate": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", + "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=" + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=" + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=" + }, + "lodash.create": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", + "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", + "requires": { + "lodash._baseassign": "3.2.0", + "lodash._basecreate": "3.0.3", + "lodash._isiterateecall": "3.0.9" + } + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=" + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=" + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "requires": { + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" + } + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.6.tgz", + "integrity": "sha1-WR2E02U6awtKO5343lqoEI5y5eA=" + }, + "mime-db": { + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.29.0.tgz", + "integrity": "sha1-SNJtI1WJZRcErFkWygYAGRQmaHg=" + }, + "mime-types": { + "version": "2.1.16", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.16.tgz", + "integrity": "sha1-K4WKUuXs1RbbiXrCvodIeDBpjiM=", + "requires": { + "mime-db": "1.29.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "1.1.8" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + }, + "mocha": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.0.tgz", + "integrity": "sha512-pIU2PJjrPYvYRqVpjXzj76qltO9uBYI7woYAMoxbSefsa+vqAfptjoeevd6bUgwD0mPIO+hv9f7ltvsNreL2PA==", + "requires": { + "browser-stdout": "1.3.0", + "commander": "2.9.0", + "debug": "2.6.8", + "diff": "3.2.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.1", + "growl": "1.9.2", + "json3": "3.3.2", + "lodash.create": "3.1.1", + "mkdirp": "0.5.1", + "supports-color": "3.1.2" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "pathval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=" + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + }, + "qs": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.0.tgz", + "integrity": "sha512-fjVFjW9yhqMhVGwRExCXLhJKrLlkYSaxNWdyc9rmHlrVZbk35YHH312dFd7191uQeXkI3mKLZTIbSvIeFwFemg==" + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "superagent": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-2.3.0.tgz", + "integrity": "sha1-cDUpoHFOV+EjlZ3e+84ZOy5Q0RU=", + "requires": { + "component-emitter": "1.2.1", + "cookiejar": "2.0.6", + "debug": "2.6.8", + "extend": "3.0.1", + "form-data": "1.0.0-rc4", + "formidable": "1.1.1", + "methods": "1.1.2", + "mime": "1.3.6", + "qs": "6.5.0", + "readable-stream": "2.3.3" + } + }, + "supports-color": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", + "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", + "requires": { + "has-flag": "1.0.0" + } + }, + "type-detect": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.3.tgz", + "integrity": "sha1-Dj8mcLRAmbC0bChNE2p+9Jx0wuo=" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "wait-port": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/wait-port/-/wait-port-0.1.4.tgz", + "integrity": "sha1-eXsQCNVOZKICkuPy5iXaRjJWU/Y=", + "requires": { + "chalk": "1.1.3", + "commander": "2.9.0", + "debug": "2.6.8" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + } + } +} diff --git a/integration/package.json b/integration/package.json new file mode 100644 index 0000000..04af63c --- /dev/null +++ b/integration/package.json @@ -0,0 +1,16 @@ +{ + "name": "bigdata4all_test", + "version": "1.0.0", + "description": "", + "scripts": { + "test": "node_modules/.bin/wait-port -t 10000 api:80 && node_modules/.bin/wait-port -t 10000 redis:6379 && node_modules/.bin/mocha" + }, + "author": "", + "license": "ISC", + "dependencies": { + "chai": "^4.1.0", + "chai-http": "^3.0.0", + "mocha": "^3.5.0", + "wait-port": "^0.1.4" + } +} diff --git a/integration/test/bigdata4all_test.js b/integration/test/bigdata4all_test.js new file mode 100644 index 0000000..156c35d --- /dev/null +++ b/integration/test/bigdata4all_test.js @@ -0,0 +1,20 @@ +let chai = require('chai'); +let chaiHttp = require('chai-http'); +let should = chai.should(); +let assert = require('assert'); + +var api_url = 'http://api'; + +chai.use(chaiHttp); + +describe('/GET health', () => { + it('it should return 200', (done) => { + chai.request(api_url) + .get('/health') + .end((err, res) => { + if (err) assert(false, 'Error in /health'); + res.should.have.status(200); + done(); + }); + }); +}); diff --git a/scripts/build.sh b/scripts/build.sh new file mode 100755 index 0000000..04ce0e3 --- /dev/null +++ b/scripts/build.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +docker build -t wtfcoderz/bigdata4all . && docker-compose up -d