Browse Source

working basic setup

Moritz Schmidt 7 years ago
parent
commit
08827824ab
12 changed files with 441 additions and 45 deletions
  1. BIN
      app
  2. 1 0
      dev/files/test.txt
  3. 1 17
      docker-compose.yml
  4. 97 25
      docker/id_rsa
  5. 25 1
      docker/id_rsa.pub
  6. 29 0
      files/models.go
  7. 21 0
      files/module.go
  8. 226 0
      files/repository.go
  9. 12 0
      files/shared.go
  10. 23 0
      files/testdata.go
  11. 4 2
      main.go
  12. 2 0
      module/errors.go

BIN
app


+ 1 - 0
dev/files/test.txt

@@ -0,0 +1 @@
+test

+ 1 - 17
docker-compose.yml

@@ -32,29 +32,13 @@ services:
       - cdn
       - proxy-nginx
     ports:
-      - "420126:420126"
+      - "3000:3000"
     environment:
       DB_HOST: db:3306
       DB_USER: cdn
       DB_PASSWORD: cdn
       VIRTUAL_HOST: cdn
 
-# weboffice:
-#      container_name: weboffice
-#      build:
-#        context: .
-#      depends_on:
-#        - db
-#      ports:
-#        - "3000:3000"
-#      restart: always
-#      volumes:
-#        - "./:/go/src/app"
-#        - "./:/usr/local/go/src/git.mmnx.de/Moe/webOffice_backend"
-#      networks:
-#        - weboffice
-
-
 volumes:
   cdn-db:
 

+ 97 - 25
docker/id_rsa

@@ -1,27 +1,99 @@
 -----BEGIN RSA PRIVATE KEY-----
-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
+MIISKQIBAAKCBAEAw3acylC+2mbEhdDJBX4vukVtLBby9YRNmX6CZ26sDocscQPc
+dWdgCv32yHrsa4IDqfJaJmw/Dm/QMQ+HX+n4pDxz/uodfO127KGjAAJJRLxZO4Vj
+4s+w2ImEgQshDI3OuU0+TN+6ft7TCy+gV7+pKonZPAfT3/RPWd2wpq9fgaV/GGbv
+s8ReAEBS1N802P7pOZs/KIVFIrjtzdcBwJaUVgW57/+1hMg24+VdlM6CVA1HgYQ2
+pcDWI+E89LlnOoh+6OxW1F/Ir+ZAd0l7dAOqTj9GJhf6jBQ9kZAHXCLDU6v+2TN/
+o9vYVZUR/ZSf1HK9xqkOP1lCN6w3LufmLzm53aP+8k9THULxTaDr4ixwb2wpm8QS
+s9aBnjvCAkWuHlg071zVFRfQe9bVughks8POFTld9GHMB54qHAPnWjxEb1oPTrqT
+0m/XaLZpi2LYf9HvV4vcYuTMkasVa8r//dNvKLdmUjLjxVmPhEKh/fbL70pCnBC8
+D/tvMNtJ3nv9gZKKkErTB3tFvGxroqnwhJQo0U9/juG6hBdxgX671s6gK6xTQCBS
+IWgkh9wmtG61pjXL/Z7W5EHlW+XPSwsj93ITxTpUBEE90IdVAkBTVuo+8acsUsSD
+pA8o0BgHigIPLPdZqfETu0FgW6YMvjw0DZI5awVeFuPM6zK+j+lEmlKL7qJ9kn+f
+MzBZxu1TxJ0QQdLNBvjGffTDdWuxr4+hWKKxdZdSzqKjThMQRFP8LfKRwI8Fhxbz
+KvBtYRpc/EIXaymGfCn9ClWelTmRunfXcG4l0wzwjnmIXhng8UHwTGtgmu7vE4/n
+R0YviOxm50maKesZv0wt+spBFzi/IlurqRNqYe1DnhEmFK8kiVLRHIPx83QUf1+H
+6AlD8//NB+MrleFTi4iSAnlLRrNSz5Ss/+ug39Fw4ZKiM/ovAI7yriwnLrWb1lkj
+nLvlyECeAxzKeZWZF1uJKetUTQBYazLg042OQV6Js3wIRQ+8QcbJK88Q3svzsgO8
+peZxUCaDTb1x4MXSDMOC8x/ZKtPB46RSytbJwi7f7StvJ41p864pdGwjWYu8U2I8
+rFYUAPdqxJFgI+6Hxu+6/uevV82KhhgU7K8ffeJuJzJdL0nHIPVawKt/A7ggGvIE
+OXJJWYLETq48r/Fa8g1tx76eWh2hiyIckcmvcprWD6FexBOnFN5ASSyKExpCcilb
+5CnTzCLgl7dwvvbfx3C2uCPG/vhvoYNw+ldKy5xPf+gg4rVc09wJAzGH1CzR1pAa
+TbE1Qs4fSxrPoQXNWiRRKjmujNfHtauF1UZ6taNVocvMvBR0HkH9DxW9fRuhYmnV
+6N4xGNl1/p7R27LftQspAwjTbLGkNs/Cn6s4TQIDAQABAoIEADonDdq7TyzXKlzN
+kyEJO9XlVeeqJDqbVCL4mn9/U702xigRiAN97/sVN9jJiZEqq0BilCOeTNxUs9IE
+1rfYelsSiUgsCv3iAGHCbSZRh87lYn7s3pzaQbkKoNtrnjeH8Rr8Oi7Q2UFptcw8
+LS4uHXxEatcLVSPqIbmQ1T+iKX3+6OMvrN0E7RqSCJLAnY55uJWk9JNvovQDpOx6
+rVDI+/Tj2z/mCfEpR/thgAgHsIqlMML9vOxvhMZD+sisaGPnvCo8NlEU9jYvALr8
+p7gKZx7EgHBQ7f/C/dZSzX3B8e7w2u9v/OeZPrGnmiShlTO1t3RlU5HRUnwRxpEz
++S3PtNaWNgGNTCMGiZgY6lTt972OpoprOU074nBbQws+A+GPSKB2NAcEgMh3UDr6
+yEsbVDLIUIWmmvchPVH8b1ZPW+TtHGTF6bjQAXxr2NbZX6QXp2eaesUJYTttdQAO
+8z5nK0kn109ZSJ6sWKB22o8eX+ofY9XevLTcj2Yvt7hzlyZ3nLX1LPeq20KF1zgb
+6yzmj4ZGaqLt0Xn/J4vpUqVD8C9OI66ObyD1RPkOrI096tk6ZChem3xphn1iz9t5
+wweZbvxcsCZb6rIhsU7sKF9RbcyjefJd+PRUdkYDACs1FaLBLHH9AWvStYJO0re+
+XZY0DNUkUavptku7WyqhsgFf0bX7J/utBD4x2vToC3XoTZTE83yd9mpHHxlX8YHf
+oo4I8iOIy/gq7379anhZh8fX6lZ2QU8RTcY66q8G6unzeW9YeykKGjtLziNW2hY6
+iy8FhrZ/fNe35PZx2WkbJrcf0569qNAvOurRtfzaj992pxTmLZ+jy7e3IsRCKfWf
+L1PK4DYFFD5UJxCd5Q/+3Zlph6VIfZcMqRtNpuehsyuFpAuhXEFEWxpxIc85nZpu
+QHN82XOmcHxC2NVj7PBGUKaVtnugPnfi4ZXS59gR3TcDAl7KNDyir25m6SoZcgbe
+7UGoURc7o5nc81IvUcUxhpjW6cegfdFC+2jZfbZjR9gzEY9M2hcbrkPlP2l8/5hG
+9k+ehYYOOllwFY9tcNnsuzUWcofiNZJclpyjRrWLnvojSa2swDVRJ0QM89QSoj0F
+jlsSK9LOtU7W/a4xdosOtZYXcamREAzB1UEMcYGALk2aINPFuVvwcrGFiLC6bIdF
+q+dKB7VzjFPN/KGzupPdYiQZ7q79i9QSzDzNWgzwnQ2rkbSyeLHckJ8FnCwiAJQ0
+8IrUFZMvfOoKUmHjhTMtTonQOE7plTpCL7Sh4wIEUGIfDatKZ/ZEAlAGDpkrgNS9
+T/bL7hL6qhON9pbyXu7h1D4q+jdxPA5d790hxudvRWZ9xTWu/dF2I4saqdhfbjmi
+JS7lr8ECggIBAPrCXVqaltCEZVNU9otVXc5sw52KzH8D7lCb58oMMdc1jjVISm/b
+TPfaoaVQbQtzhgebQXaGF5iXI4rZlrrF+38Rgk7DfVWpwwZbFyX/Fj0HzM+5sQAQ
+4ubEOao+tXDZJuFlityg/Lst04TKuiswwPr8Imw9S6SEAaAr9LELqUhWfskag0+y
+nCcbi7jHq/bezhQRCIjocvn4R70LvbrE6dELYTEdaEopYKa9QlOU6X7cOrPTY3jV
+eVqxhtV3LNNtVT2N/CaZ7/hJGVE2f8W451+fWGSBxnwXRKTabiASWpAtHCUiBSOT
+lCUmXR+wc+hWlrTQFCTAIj1ru2nUlHB9LTFwlESTh1LwnSaMut3soMgMWSb/sC+A
+6QL9y7uDTuORuILBp6tBwvPJ8CJFV8n6dYKSl0d4Ks4L1+WVSKyzeCuL7ruO19Sa
+tel8i0xwrJx0e5KT58YBkUnyAHrpulvHpo7fQQfNIkkdr+zlatRDdPULajsYqjlM
+ou7cDl8ucBDVns9exv1WGpTWnOi3JjJIoZ8Sy8sbLMRNFFbz2/uBvCTHYcpjUEhT
+Oak7X8o8pRkrB+qNtc9BpDDV2cVQTcYLActTxPrdh5h7s4lpBQ+N5oX9+jXYGFNp
+azew162NcYczZ6EYkr5yuLei5fr7CpdZ8wi8IVhP54UBK1USDOR8Rfv5AoICAQDH
+jGYEe1HOtIj+prFRhUByW7EkUzgcGm1ZmGgawzehtT50PvXdc2Rdtrbu1cC8jBoJ
+e++Tz4JLo2vHmBhRqH1TJ3e3B2cCsBrACL2bBe8xCEzfYK6hy3U2ledfkuPGcaXs
+JiDV5PWLzD2Ow8wwnSLW63p8WASoc76kLYFN7BWNaAfNUQ128ooG1L2YNajHf0I0
+o+D8UgfbXPLR3bpBt45KgglVTdZP3GRH+KRlvKg1mMSp9LIFyPKbD62jrQb7Fknx
+GHmk2ZA4CJI8iIv8CYrC3yVboQyqZpfomtAzQ1GTFEapgUFcmozX1DvKRlGyaVmY
+dKKRC83VGTZeQLDs+xsXMl0FgHPMA7GrQxQ5kTwOuiu969kBvQcvbkm3yOqFhTjo
+Q3l8NYhk+gzsCrW3PF+n04KkWjnL1F6ZDMCoXcKqdZT0CeubtS0oIeqV9NzvacgS
+jvjH1KZT2rY0Gd9JKEdDel3rAgn8+ctoa8/fLZztdSSpDE9YTurzuvqaURC6j4n1
+xbOcZn4TDM5xiCvJeXSdNkuN5lslpi1Zlo1tH687PlN2/ZCef7PocjFiXkOCVxX8
+h8A+naL83T9Q42lVmgGMo0wU40Kv2bUP8uvG3ddED3zWZA0zCqVgpgUX3QiLBUC6
+8YEx8WKUM+7z926TsJ6GAnIqYm7jtzZ/+LhGS2Br9QKCAgAoshqMdcI8HQCEwakx
+e605rxUgIEKH6o9mraa0d74u+xYVN6I8/Q5Eu0q4lZDc5ua9nUjGf4Sc0wqFokKA
+FVl3idPoDHnuyRpJkcbz964YQYfPvocnR5ZLdVUWeA7iPZu9wMkEfWwGxK0rQ+tq
+zwLCuOCtSFVaYcIRyJBxmz7h6oexA4iECqyk/Cd02ZLjAc3YG9uSvIbMYqrh12H3
+SbXYo0wmuGsQfh6dcOGuxuAOIpe0T345Qgvr2BvV0P2JYpkO4Fgnu5viY5qkP4AF
+CrkiH64swZMA2JXfW0O8GL5x36BNtnO3DmBglxVN60kkT8ktlwdt33CvHyjPSBy/
+FNGc0HR/nKG9qCcY9oXtNlXxoW9mkOB7FSS7w4yo5eqLrD6RmfQoKwgEoKVEKpTQ
+xsEDa975TltEDVAAhnXA8W9zQcaA0fHdIy6asge5ZB/fVFgpta9Lxz1ZDtldGUmR
+U5mIXlsjdPs3eoXuoFzyDfCRRET9Skd1/SYENdpvQA4X7VNUvED3JF40AZB9hBvC
+1V7FfjtsvwBI62l9ox30d12dam5Idk21LyyQdn5ZR/ZTW1RxkIYNGM4YztwE1b+J
+gIfOA85YGFPFP24nws97csASxuEwk91+zAEGjMCz/dyK4KDU2DQYjG3F/73rOYrC
+fWqf5EhVGMKuJz5tE/zbp/+DoQKCAgEAvyzYNCT9bD50HRwQN1ylMKp93KJJ2ErN
+RpAH9NPggXFFw1LqdF3v4wSA3/Izc6/55eoxzfd5CgQn5xHlAp6casUeIWDbJK0Z
+A6+cD2AxF1WvaDaVN/bXdhNJlrwAsocBAmxI+wMe5+8lbphREKYK0cLKF0SwOb6h
+/2KFReUPhOkMyHyFnNaivAanGaMW7wIRqKL0kmf4lQXIsJ1vqzQzA1jvniUzVFF+
+VaF1xu5mbOrOR1FiGL67BymPHodPb9CbyHq9V90EGVrE12+uRSnTIf1tKgryOnKN
+yNBA9UviZDmBtTVbLF/43XG8Un7qGDZsGu5rLPEVIrrD5qqtlmzAOIoMqo+04NkN
+J1ndj4V/91APRiYlQlAaCSvtPkEjxgWrToIOapxS7wLMzHs6OrGBpySxPcofIxN0
+Ccc48FTbgjmiGedDLWr3N0K/Hyl3XXuHrZgB6ljlfOLFusaqr8kB9TjPr63FafLb
+GFBp15Q4ixq2o6pifeUlnZoeKyfNEh8gejENcaKT2KZlRknCQYS130Q8QFdYLYq2
+WeUt20UGuYhtqEsneWI5N1Hn1CkhHkdWjhh0asjVdNJ2rYUhzlv8bgOoiT5tDlJR
+8FS35E92xALeg/tY1fS2GhEUQheF7sJ6kF99eh6bZgcXP+5mpuIIDbVcMRUazdki
+QppD2TyvxN0CggIBAPALedXMvZy2ERhhOCimhRsDLL8Og26cz6S2maOudkzNZqlc
+Yf6vI8ikQL6OpyoGwiTKSNI6uiiAeaEYfJZMG5dLy8BVoJdD71Hh3TJr8/zObLM6
+IILhBIuWmMuPWOwz6FxGDTenEihCtq3jIh5pQTlrVzA/H+G0ZfAcQQ6gklejIAcm
++BFCoVMzTuhQ2AaEgVKPfR9lIeYmNh4jKIp39SM+Enkz0r7i0fsgsW3GQlz2djNk
+lhF5+2Xn4lLnoGf9exxtUIYszFwMEnWcOrFIXfY5qc7NbBfsPyw1DckX/TtmyASk
+3/xnEf/v4tIAhRAfQe5B5qCHiZwjNvz/TZrDP0FWvrWOShgahdoyasvgH+xI1bMZ
+lWAj6QYCM6c2qAi+xDgHZ/RIRlXUQPiyrwGwoeC06RmxBL/xOGgbYmKImwhhfwaW
+x1m4jcEyXhbp/R730Z9/UHUTO6gXkswDR3IoakRHdTokozZcZRdm9a8fKFTp5E6R
+twFAPwLeF5B2upzV05hXu6AUK/JCAg9fIaabic/xqsTBf+PmfkP+P2ndSpAuXpoz
+Z7aVQg4+4yPGwULv3wacvCnUNewXTkCGwIQkWobgqkcHVOLuPlQLZe5XnqO+EM5M
+BnM/3og0qXBtY9k++kcJBv6kxL/bL+biOqfF2td9fQTW+xCLBhgcgBLs0p/a
 -----END RSA PRIVATE KEY-----

+ 25 - 1
docker/id_rsa.pub

@@ -1 +1,25 @@
-ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDZhF8x+KpDhbTSIK9+MHR+rveqcvDXx6SurkHY+9EyG6NyJ8A08IL+Wwn0rWtGwOB0mELZK2Qk9/36MLLJNSfuTHhA3FuTNoKParHXJ3QhG/dL32ms5KGkYYFT73RhpZk/zmBUmvyEabvadyu6ZxslUO32zziUu70Ppu0xrdZm0wZnyB4zxiD4rgQhAQYzv3Mk93OhponINUr8sTpgG+wlbap+5s9HtpCQrqasK09/7NaTKb/Iz0FDOza/b846JCeYjNpqmfOPWKofA28a36IGhd+xjprzbGYMEC4axGJ6szXQC+VFbUhCfPIB4fktf6DED1XEjHBbqhoH3GdGwZMT m@hotdog
+-----BEGIN PUBLIC KEY-----
+MIIEIjANBgkqhkiG9w0BAQEFAAOCBA8AMIIECgKCBAEAw3acylC+2mbEhdDJBX4v
+ukVtLBby9YRNmX6CZ26sDocscQPcdWdgCv32yHrsa4IDqfJaJmw/Dm/QMQ+HX+n4
+pDxz/uodfO127KGjAAJJRLxZO4Vj4s+w2ImEgQshDI3OuU0+TN+6ft7TCy+gV7+p
+KonZPAfT3/RPWd2wpq9fgaV/GGbvs8ReAEBS1N802P7pOZs/KIVFIrjtzdcBwJaU
+VgW57/+1hMg24+VdlM6CVA1HgYQ2pcDWI+E89LlnOoh+6OxW1F/Ir+ZAd0l7dAOq
+Tj9GJhf6jBQ9kZAHXCLDU6v+2TN/o9vYVZUR/ZSf1HK9xqkOP1lCN6w3LufmLzm5
+3aP+8k9THULxTaDr4ixwb2wpm8QSs9aBnjvCAkWuHlg071zVFRfQe9bVughks8PO
+FTld9GHMB54qHAPnWjxEb1oPTrqT0m/XaLZpi2LYf9HvV4vcYuTMkasVa8r//dNv
+KLdmUjLjxVmPhEKh/fbL70pCnBC8D/tvMNtJ3nv9gZKKkErTB3tFvGxroqnwhJQo
+0U9/juG6hBdxgX671s6gK6xTQCBSIWgkh9wmtG61pjXL/Z7W5EHlW+XPSwsj93IT
+xTpUBEE90IdVAkBTVuo+8acsUsSDpA8o0BgHigIPLPdZqfETu0FgW6YMvjw0DZI5
+awVeFuPM6zK+j+lEmlKL7qJ9kn+fMzBZxu1TxJ0QQdLNBvjGffTDdWuxr4+hWKKx
+dZdSzqKjThMQRFP8LfKRwI8FhxbzKvBtYRpc/EIXaymGfCn9ClWelTmRunfXcG4l
+0wzwjnmIXhng8UHwTGtgmu7vE4/nR0YviOxm50maKesZv0wt+spBFzi/IlurqRNq
+Ye1DnhEmFK8kiVLRHIPx83QUf1+H6AlD8//NB+MrleFTi4iSAnlLRrNSz5Ss/+ug
+39Fw4ZKiM/ovAI7yriwnLrWb1lkjnLvlyECeAxzKeZWZF1uJKetUTQBYazLg042O
+QV6Js3wIRQ+8QcbJK88Q3svzsgO8peZxUCaDTb1x4MXSDMOC8x/ZKtPB46RSytbJ
+wi7f7StvJ41p864pdGwjWYu8U2I8rFYUAPdqxJFgI+6Hxu+6/uevV82KhhgU7K8f
+feJuJzJdL0nHIPVawKt/A7ggGvIEOXJJWYLETq48r/Fa8g1tx76eWh2hiyIckcmv
+cprWD6FexBOnFN5ASSyKExpCcilb5CnTzCLgl7dwvvbfx3C2uCPG/vhvoYNw+ldK
+y5xPf+gg4rVc09wJAzGH1CzR1pAaTbE1Qs4fSxrPoQXNWiRRKjmujNfHtauF1UZ6
+taNVocvMvBR0HkH9DxW9fRuhYmnV6N4xGNl1/p7R27LftQspAwjTbLGkNs/Cn6s4
+TQIDAQAB
+-----END PUBLIC KEY-----

+ 29 - 0
files/models.go

@@ -0,0 +1,29 @@
+package files
+
+import "github.com/jinzhu/gorm"
+
+const (
+	filetype_text = iota
+	filetype_image = iota
+	filetype_video = iota
+	filetype_audio = iota
+
+)
+
+type File struct {
+	gorm.Model
+
+	Storage Storage
+	StorageID uint
+
+	RelativePath string
+	FileType int
+}
+
+type Storage struct {
+	gorm.Model
+
+	AbsolutePath string
+}
+
+// TODO storage

+ 21 - 0
files/module.go

@@ -0,0 +1,21 @@
+package files
+
+import (
+	"git.mmnx.de/mmnx/cdn/module"
+)
+
+// RegisterModule calls neccessary actions for this module to work
+func RegisterModule(paramConf *module.Config) {
+	conf = paramConf
+	db = conf.DB
+	storagePath = "/go/src/app/dev/files/"
+
+	// (Auto-)Migrate all models
+	db.AutoMigrate(&File{}, &Storage{})
+
+	// register HTTP APIs
+	module.NegroniRoute(conf.Router, conf.BasePath, "/files", "GET POST PUT", filesIndex)
+	module.NegroniRoute(conf.Router, conf.BasePath, "/files/{fileID}", "GET PATCH DELETE", filesSingle)
+	module.NegroniRoute(conf.Router, conf.BasePath, "/files/{fileID}/file", "GET", filesRaw)
+	module.NegroniRoute(conf.Router, conf.BasePath, "/mock/files", "GET", mockFiles)
+}

+ 226 - 0
files/repository.go

@@ -0,0 +1,226 @@
+package files
+
+import (
+	// "errors"
+	"net/http"
+	"io/ioutil"
+	// "strconv"
+	// "strings"
+
+	"git.mmnx.de/mmnx/cdn/module"
+	"github.com/gorilla/mux"
+)
+
+//TODO test mux var
+
+// repository.go holds all basic HTTP API methods
+
+func filesIndex(w http.ResponseWriter, r *http.Request) {
+	switch r.Method {
+	case "GET":
+		getFiles(w, r)
+		// getContacts(w, r)
+		break
+	case "POST":
+		// postContact(w, r)
+		break
+	case "PUT":
+		// putContact(w, r)
+		break
+	}
+}
+
+func filesSingle(w http.ResponseWriter, r *http.Request) {
+	switch r.Method {
+	case "GET":
+		// getContact(w, r)
+		break
+	case "PATCH":
+		// patchContact(w, r)
+		break
+	case "DELETE":
+		// deleteContact(w, r)
+		break
+	}
+}
+
+func filesRaw(w http.ResponseWriter, r *http.Request) {
+	if r.Method == "GET" {
+		fileID := mux.Vars(r)["fileID"]
+		file := &File{}
+
+		// get file from DB
+		module.HandleError(module.ErrDatabase, db.Preload("Storage").Find(&file, "id = ?", fileID).Error)
+
+		// read file contents
+		dat, err := ioutil.ReadFile(file.Storage.AbsolutePath + file.RelativePath)
+		module.HandleError(module.ErrReadingFile, err)
+
+		// output file contents
+		w.Write(dat)
+	}
+}
+
+
+func getFiles(w http.ResponseWriter, r *http.Request) {
+	files := []File{}
+
+	module.HandleError(module.ErrDatabase, db.Preload("Storage").Find(&files).Error) // get db records
+
+	module.JSONResp(w, files)
+}
+
+
+
+func mockFiles(w http.ResponseWriter, r *http.Request) {
+	createTestData()
+	// files := []File{}
+
+	// for i := range people {
+	// 	// "convert" us house-nr format to eu
+	// 	street := strings.Title(people[i].Location["street"].(string))
+	// 	streetSpl := strings.Split(street, " ")
+	// 	houseNr, err := strconv.Atoi(streetSpl[0])
+	// 	module.HandleError(module.ErrParsingInt, err)
+	// 	houseNr = houseNr / 400
+	// 	street = strings.Join(streetSpl[1:], " ") + " " + strconv.Itoa(houseNr)
+
+	// 	con := Contact{
+	// 		Prefix: func(t string) string {
+	// 			if t == "mr" {
+	// 				return "Hr."
+	// 			}
+	// 			return "Fr."
+	// 		}(people[i].Name["title"]),
+	// 		FirstName: strings.Title(people[i].Name["first"]),
+	// 		LastName:  strings.Title(people[i].Name["last"]),
+
+	// 		Phones:    []Phone{Phone{Type: "Mobil", Number: people[i].Cell}, Phone{Type: "Privat", Number: people[i].Phone}},
+	// 		Emails:    []Email{Email{Type: "Privat", Address: people[i].Email}},
+	// 		Addresses: []Address{Address{Type: "Privat", Street: street, ZIPCode: strconv.FormatFloat(people[i].Location["postcode"].(float64), 'g', 5, 64), City: strings.Title(people[i].Location["city"].(string)), State: strings.Title(people[i].Location["state"].(string)), Country: "Deutschland"}},
+	// 	}
+
+	// 	cons = append(cons, con)
+	// 	module.HandleError(module.ErrDatabase, db.Create(&con).Error) // create in DB
+	// }
+
+	module.JSONResp(w, "done")
+}
+
+// func getContacts(w http.ResponseWriter, r *http.Request) {
+// 	contacts := []Contact{}
+
+// 	module.HandleError(module.ErrDatabase, db.Preload("Emails").Preload("Phones").Preload("Addresses").Find(&contacts).Error) // get db records
+
+// 	module.JSONResp(w, contacts)
+// }
+
+// func getContact(w http.ResponseWriter, r *http.Request) {
+// 	// contact := Contact{}
+// 	//
+// 	// module.HandleError(module.ErrDatabase, db.Preload("Emails").Preload("Phones").Preload("Addresses").First(&contact, "id = ?", mux.Vars(r)["contactID"]).Error) // get DB record with relations
+
+// 	module.JSONResp(w, getFullContact(mux.Vars(r)["contactID"]))
+// }
+
+// func postContact(w http.ResponseWriter, r *http.Request) {
+// 	contact := Contact{}
+// 	module.JSONReq(r, &contact) // decode POST data
+
+// 	module.HandleError(module.ErrDatabase, db.Create(&contact).Error) // create in DB
+
+// 	module.JSONResp(w, getFullContact(strconv.Itoa(int(contact.ID))))
+
+// }
+
+// func putContact(w http.ResponseWriter, r *http.Request) {
+// 	contact := Contact{}
+// 	module.JSONReq(r, &contact) // decode POST data
+
+// 	module.HandleError(module.ErrDatabase, db.Save(&contact).Error) // update in DB
+
+// 	module.JSONResp(w, getFullContact(strconv.Itoa(int(contact.ID))))
+// }
+
+// func patchContact(w http.ResponseWriter, r *http.Request) {
+// 	var updates []map[string]interface{}
+// 	parsedUpdates := make(map[string]interface{})
+// 	contact := Contact{}
+// 	module.JSONReq(r, &updates) // decode POST data
+
+// 	for i := range updates {
+// 		for k, v := range updates[i] {
+// 			parsedUpdates[k] = v
+// 		}
+// 	}
+
+// 	module.HandleError(module.ErrDatabase, db.Find(&contact, "id = ?", mux.Vars(r)["contactID"]).Error) // get contact
+// 	module.HandleError(module.ErrDatabase, db.Model(&contact).Update(parsedUpdates).Error)              // update
+
+// 	contact = Contact{}
+// 	module.JSONResp(w, getFullContact(mux.Vars(r)["contactID"]))
+// }
+
+// func deleteContact(w http.ResponseWriter, r *http.Request) {
+// 	count := -1
+
+// 	module.HandleError(module.ErrDatabase, db.Model(Contact{}).Where("id = ?", mux.Vars(r)["contactID"]).Count(&count).Error) // get contact count with contactID
+
+// 	if count != 1 { // contact has to be identifiable
+// 		module.HandleError(module.ErrDatabase, errors.New("record not found"))
+// 	}
+
+// 	module.HandleError(module.ErrDatabase, db.Delete(Contact{}, mux.Vars(r)["contactID"]).Error) // soft delete
+
+// 	status := make(map[string]string)
+
+// 	status["status"] = "ok"
+
+// 	module.JSONResp(w, status)
+// }
+
+// // mockContacts gets some random person data and fills the database with them
+// func mockContacts(w http.ResponseWriter, r *http.Request) {
+// 	people := createRandomTestData()
+// 	cons := []Contact{}
+
+// 	for i := range people {
+// 		// "convert" us house-nr format to eu
+// 		street := strings.Title(people[i].Location["street"].(string))
+// 		streetSpl := strings.Split(street, " ")
+// 		houseNr, err := strconv.Atoi(streetSpl[0])
+// 		module.HandleError(module.ErrParsingInt, err)
+// 		houseNr = houseNr / 400
+// 		street = strings.Join(streetSpl[1:], " ") + " " + strconv.Itoa(houseNr)
+
+// 		con := Contact{
+// 			Prefix: func(t string) string {
+// 				if t == "mr" {
+// 					return "Hr."
+// 				}
+// 				return "Fr."
+// 			}(people[i].Name["title"]),
+// 			FirstName: strings.Title(people[i].Name["first"]),
+// 			LastName:  strings.Title(people[i].Name["last"]),
+
+// 			Phones:    []Phone{Phone{Type: "Mobil", Number: people[i].Cell}, Phone{Type: "Privat", Number: people[i].Phone}},
+// 			Emails:    []Email{Email{Type: "Privat", Address: people[i].Email}},
+// 			Addresses: []Address{Address{Type: "Privat", Street: street, ZIPCode: strconv.FormatFloat(people[i].Location["postcode"].(float64), 'g', 5, 64), City: strings.Title(people[i].Location["city"].(string)), State: strings.Title(people[i].Location["state"].(string)), Country: "Deutschland"}},
+// 		}
+
+// 		cons = append(cons, con)
+// 		module.HandleError(module.ErrDatabase, db.Create(&con).Error) // create in DB
+// 	}
+
+// 	module.JSONResp(w, cons)
+// }
+
+// // Helpers
+
+// func getFullContact(contactID string) Contact {
+// 	contact := Contact{}
+
+// 	module.HandleError(module.ErrDatabase, db.Preload("Emails").Preload("Phones").Preload("Addresses").First(&contact, "id = ?", contactID).Error) // get DB record with relations
+
+// 	return contact
+// }

+ 12 - 0
files/shared.go

@@ -0,0 +1,12 @@
+package files
+
+import (
+	"git.mmnx.de/mmnx/cdn/module"
+	"github.com/jinzhu/gorm"
+)
+
+var (
+	db   *gorm.DB
+	conf *module.Config
+	storagePath string
+)

+ 23 - 0
files/testdata.go

@@ -0,0 +1,23 @@
+package files
+
+import (
+	"log"
+	"git.mmnx.de/mmnx/cdn/module"
+)
+
+func createTestData() {
+	storage := &Storage{AbsolutePath: "/go/src/app/dev/files/"}
+
+	module.HandleError(module.ErrDatabase, db.Create(storage).Error)
+
+	// storage := &Storage{}
+	// db.First(&storage, "id = ?", storage.ID)
+	log.Printf("%#v", storage)
+
+	module.HandleError(module.ErrDatabase, db.Create(&File{
+		RelativePath: "test.txt",
+		FileType: filetype_text,
+		StorageID: storage.ID,
+		Storage: *storage,
+		}).Error)
+}

+ 4 - 2
main.go

@@ -12,6 +12,7 @@ import (
 	// "git.mmnx.de/Moe/webOffice_backend/contacts"
 	// "git.mmnx.de/Moe/webOffice_backend/module"
 	"git.mmnx.de/mmnx/cdn/module"
+	"git.mmnx.de/mmnx/cdn/files"
 	
 	"github.com/gorilla/mux"
 	"github.com/jinzhu/gorm"
@@ -22,7 +23,7 @@ import (
 
 func connectDB(host string) *gorm.DB {
 	time.Sleep(250 * time.Millisecond) // let mysql startup
-	db, err := gorm.Open("mysql", "wo:wo@tcp("+host+")/weboffice?charset=utf8mb4&parseTime=True&loc=Local")
+	db, err := gorm.Open("mysql", "root:root@tcp("+host+")/cdn?charset=utf8mb4&parseTime=True&loc=Local")
 	if err != nil {
 		if strings.HasPrefix(err.Error(), "default addr for network") {
 			log.Println("Reconnecting..")
@@ -68,6 +69,7 @@ func main() {
 	module.Conf = modConf
 
 	// contacts.RegisterModule(&modConf)
+	files.RegisterModule(&modConf)
 
 	module.NegroniRoute(apiV1, "/api/v1", "/test", "GET", HandlerFunc, AuthFunc)
 
@@ -75,7 +77,7 @@ func main() {
 	n.Use(module.NewHTTPStatusHandler())
 	n.Use(c)
 	n.UseHandler(router)
-	n.Run(":420126")
+	n.Run(":3000")
 
 }
 

+ 2 - 0
module/errors.go

@@ -31,6 +31,7 @@ var (
 	ErrDatabase           = errors.New("Database error")
 	ErrRetrievingTestData = errors.New("Error receiving Testdata")
 	ErrParsingInt         = errors.New("Error parsing string to int")
+	ErrReadingFile				= errors.New("Error reading file")
 )
 
 // StatusCodeMapper maps errors to HTTP Status codes
@@ -55,6 +56,7 @@ var StatusCodeMapper = map[error]int{
 	ErrDatabase:           http.StatusInternalServerError,
 	ErrRetrievingTestData: http.StatusBadGateway,
 	ErrParsingInt:         http.StatusInternalServerError,
+	ErrReadingFile: 				http.StatusInternalServerError,
 }
 
 // MetaError is two errors in one