Commit 6a5c6931ebe949e22aada7d63497bcff1ac6c402

Authored by Marko Tikvić
1 parent 2c237577d3
Exists in master

added database map to server

document/document.go
1 package document 1 package document
2 2
3 import ( 3 import (
4 "errors" 4 "errors"
5 "fmt" 5 "fmt"
6 "io" 6 "io"
7 "mime" 7 "mime"
8 "net/http" 8 "net/http"
9 "os" 9 "os"
10 "strings"
11 "time" 10 "time"
12 11
13 web "git.to-net.rs/marko.tikvic/webutility" 12 web "git.to-net.rs/marko.tikvic/webutility"
14 ) 13 )
15 14
16 // Document ... 15 // Document ...
17 type Document struct { 16 type Document struct {
18 ID int64 `json:"id"` 17 ID int64 `json:"id"`
19 FileName string `json:"fileName"` 18 FileName string `json:"fileName"`
20 Extension string `json:"extension"` 19 Extension string `json:"extension"`
21 ContentType string `json:"contentType"` 20 ContentType string `json:"contentType"`
22 Size int64 `json:"fileSize"` 21 Size int64 `json:"fileSize"`
23 UploadedBy string `json:"uploadedBy"` 22 UploadedBy string `json:"uploadedBy"`
24 LastModifiedBy string `json:"lastModifiedBy"` 23 LastModifiedBy string `json:"lastModifiedBy"`
25 TimeUploaded int64 `json:"timeUploaded"` 24 TimeUploaded int64 `json:"timeUploaded"`
26 TimeLastModified int64 `json:"timeLastModified"` 25 TimeLastModified int64 `json:"timeLastModified"`
27 RoleAccessLevel int64 `json:"accessLevel"` 26 RoleAccessLevel int64 `json:"accessLevel"`
28 Description string `json:"description"` 27 Description string `json:"description"`
29 Download *DownloadLink `json:"download"` 28 Download *DownloadLink `json:"download"`
30 Path string `json:"-"` 29 Path string `json:"-"`
31 directory string 30 directory string
32 data []byte 31 data []byte
33 } 32 }
34 33
35 // OpenFileAsDocument ... 34 // OpenFileAsDocument ...
36 func OpenFileAsDocument(path string) (*Document, error) { 35 func OpenFileAsDocument(path string) (*Document, error) {
37 d := &Document{Path: path} 36 d := &Document{Path: path}
38 37
39 f, err := os.Open(d.Path) 38 f, err := os.Open(d.Path)
40 if err != nil { 39 if err != nil {
41 return nil, err 40 return nil, err
42 } 41 }
43 defer f.Close() 42 defer f.Close()
44 43
45 stats, err := f.Stat() 44 stats, err := f.Stat()
46 if err != nil { 45 if err != nil {
47 return nil, err 46 return nil, err
48 } 47 }
49 48
50 d.FileName = stats.Name() 49 d.FileName = stats.Name()
51 d.Size = stats.Size() 50 d.Size = stats.Size()
52 d.Extension = FileExtension(d.FileName) 51 d.Extension = web.FileExtension(d.FileName)
53 52
54 d.data = make([]byte, d.Size) 53 d.data = make([]byte, d.Size)
55 if _, err = f.Read(d.data); err != nil { 54 if _, err = f.Read(d.data); err != nil {
56 return nil, err 55 return nil, err
57 } 56 }
58 57
59 return d, err 58 return d, err
60 } 59 }
61 60
62 // DownloadLink ... 61 // DownloadLink ...
63 type DownloadLink struct { 62 type DownloadLink struct {
64 Method string `json:"method"` 63 Method string `json:"method"`
65 URL string `json:"url"` 64 URL string `json:"url"`
66 } 65 }
67 66
68 // SetDownloadInfo ... 67 // SetDownloadInfo ...
69 func (d *Document) SetDownloadInfo(method, url string) { 68 func (d *Document) SetDownloadInfo(method, url string) {
70 d.Download = &DownloadLink{ 69 d.Download = &DownloadLink{
71 Method: method, 70 Method: method,
72 URL: url, 71 URL: url,
73 } 72 }
74 } 73 }
75 74
76 // ServeDocument writes d's buffer to w and sets appropriate headers according to d's content type 75 // ServeDocument writes d's buffer to w and sets appropriate headers according to d's content type
77 // and downloadPrompt. 76 // and downloadPrompt.
78 func ServeDocument(w http.ResponseWriter, d *Document, downloadPrompt bool) error { 77 func ServeDocument(w http.ResponseWriter, d *Document, downloadPrompt bool) error {
79 f, err := os.Open(d.Path) 78 f, err := os.Open(d.Path)
80 if err != nil { 79 if err != nil {
81 return err 80 return err
82 } 81 }
83 defer f.Close() 82 defer f.Close()
84 83
85 web.SetContentType(w, mime.TypeByExtension(d.Extension)) 84 web.SetContentType(w, mime.TypeByExtension(d.Extension))
86 web.SetResponseStatus(w, http.StatusOK) 85 web.SetResponseStatus(w, http.StatusOK)
87 if downloadPrompt { 86 if downloadPrompt {
88 w.Header().Set("Content-Disposition", "attachment; filename="+d.FileName) 87 w.Header().Set("Content-Disposition", "attachment; filename="+d.FileName)
89 } 88 }
90 89
91 buf := make([]byte, d.Size) 90 buf := make([]byte, d.Size)
92 if _, err := f.Read(buf); err != nil { 91 if _, err := f.Read(buf); err != nil {
93 return err 92 return err
94 } 93 }
95 94
96 w.Header().Set("Content-Length", fmt.Sprintf("%d", d.Size)) 95 w.Header().Set("Content-Length", fmt.Sprintf("%d", d.Size))
97 web.WriteResponse(w, buf) 96 web.WriteResponse(w, buf)
98 97
99 return nil 98 return nil
100 } 99 }
101 100
102 // FileExists ...
103 func FileExists(path string) bool {
104 temp, err := os.Open(path)
105 defer temp.Close()
106
107 if err != nil {
108 return false
109 }
110
111 return true
112 }
113
114 // ParseDocument ... 101 // ParseDocument ...
115 func ParseDocument(req *http.Request) (doc *Document, err error) { 102 func ParseDocument(req *http.Request) (doc *Document, err error) {
116 req.ParseMultipartForm(32 << 20) 103 req.ParseMultipartForm(32 << 20)
117 file, fheader, err := req.FormFile("document") 104 file, fheader, err := req.FormFile("document")
118 if err != nil { 105 if err != nil {
119 return doc, err 106 return doc, err
120 } 107 }
121 108
122 claims, _ := web.GetTokenClaims(req) 109 claims, _ := web.GetTokenClaims(req)
123 owner := claims.Username 110 owner := claims.Username
124 111
125 fname := fheader.Filename 112 fname := fheader.Filename
126 113
127 fsize := fheader.Size 114 fsize := fheader.Size
128 ftype := fmt.Sprintf("%v", fheader.Header["Content-Type"][0]) 115 ftype := fmt.Sprintf("%v", fheader.Header["Content-Type"][0])
129 116
130 fextn := FileExtension(fname) 117 fextn := web.FileExtension(fname)
131 if fextn == "" { 118 if fextn == "" {
132 return doc, errors.New("invalid extension") 119 return doc, errors.New("invalid extension")
133 } 120 }
134 121
135 doc = new(Document) 122 doc = new(Document)
136 123
137 doc.FileName = fname 124 doc.FileName = fname
138 doc.Size = fsize 125 doc.Size = fsize
139 doc.ContentType = ftype 126 doc.ContentType = ftype
140 doc.Extension = "." + fextn 127 doc.Extension = "." + fextn
141 128
142 t := time.Now().Unix() 129 t := time.Now().Unix()
143 doc.TimeUploaded = t 130 doc.TimeUploaded = t
144 doc.TimeLastModified = t 131 doc.TimeLastModified = t
145 132
146 doc.UploadedBy = owner 133 doc.UploadedBy = owner
147 doc.LastModifiedBy = owner 134 doc.LastModifiedBy = owner
148 doc.RoleAccessLevel = 0 135 doc.RoleAccessLevel = 0
149 136
150 doc.data = make([]byte, doc.Size) 137 doc.data = make([]byte, doc.Size)
151 if _, err = io.ReadFull(file, doc.data); err != nil { 138 if _, err = io.ReadFull(file, doc.data); err != nil {
152 return doc, err 139 return doc, err
153 } 140 }
154 141
155 return doc, nil 142 return doc, nil
156 } 143 }
157 144
158 // DirectoryFromPath ...
159 func DirectoryFromPath(path string) (dir string) {
160 parts := strings.Split(path, "/")
161 if len(parts) == 1 {
162 return ""
163 }
164
165 dir = parts[0]
166 for _, p := range parts[1 : len(parts)-1] {
167 dir += "/" + p
168 }
169
170 return dir
171 }
172
173 // SaveToFile ... 145 // SaveToFile ...
174 func (d *Document) SaveToFile(path string) (f *os.File, err error) { 146 func (d *Document) SaveToFile(path string) (f *os.File, err error) {
175 d.Path = path 147 d.Path = path
176 148
177 if FileExists(path) { 149 if web.FileExists(path) {
178 err = fmt.Errorf("file %s alredy exists", path) 150 err = fmt.Errorf("file %s alredy exists", path)
179 return nil, err 151 return nil, err
180 } 152 }
181 153
182 if parentDir := DirectoryFromPath(path); parentDir != "" { 154 if parentDir := web.DirectoryFromPath(path); parentDir != "" {
183 if err = os.MkdirAll(parentDir, os.ModePerm); err != nil { 155 if err = os.MkdirAll(parentDir, os.ModePerm); err != nil {
184 if !os.IsExist(err) { 156 if !os.IsExist(err) {
185 return nil, err 157 return nil, err
186 } 158 }
187 } 159 }
188 } 160 }
189 161
190 if f, err = os.Create(path); err != nil { 162 if f, err = os.Create(path); err != nil {
191 return nil, err 163 return nil, err
192 } 164 }
193 165
194 if _, err = f.Write(d.data); err != nil { 166 if _, err = f.Write(d.data); err != nil {
195 f.Close() 167 f.Close()
196 d.DeleteFile() 168 d.DeleteFile()
197 return nil, err 169 return nil, err
198 } 170 }
199 f.Close() 171 f.Close()
200 172
201 return f, nil 173 return f, nil
202 } 174 }
203 175
204 func DeleteFile(path string) error {
205 return os.Remove(path)
206 }
207
208 func DeleteDocuments(docs []*Document) error { 176 func DeleteDocuments(docs []*Document) error {
209 for _, d := range docs { 177 for _, d := range docs {
210 if err := d.DeleteFile(); err != nil { 178 if err := d.DeleteFile(); err != nil {
211 return err 179 return err
212 } 180 }
213 } 181 }
214 return nil 182 return nil
215 } 183 }
216 184
217 // DeleteFile ... 185 // DeleteFile ...
218 func (d *Document) DeleteFile() error { 186 func (d *Document) DeleteFile() error {
219 return os.Remove(d.Path) 187 return os.Remove(d.Path)
220 } 188 }
221
222 func FileExtension(path string) string {
223 parts := strings.Split(path, ".") // because name can contain dots
224 if len(parts) < 2 {
225 return ""
226 }
227 return "." + parts[len(parts)-1]
228 }
229 189
1 package webutility 1 package webutility
2 2
3 import ( 3 import (
4 "bytes" 4 "bytes"
5 "fmt"
5 "io" 6 "io"
6 "io/ioutil" 7 "io/ioutil"
7 "os" 8 "os"
8 "strings" 9 "strings"
9 ) 10 )
10 11
11 // ReadFileContent ... 12 // ReadFileContent ...
12 func ReadFileContent(path string) ([]byte, error) { 13 func ReadFileContent(path string) ([]byte, error) {
13 f, err := os.Open(path) 14 f, err := os.Open(path)
14 if err != nil { 15 if err != nil {
15 return nil, err 16 return nil, err
16 } 17 }
17 defer f.Close() 18 defer f.Close()
18 19
19 buf := &bytes.Buffer{} 20 buf := &bytes.Buffer{}
20 if _, err = io.Copy(buf, f); err != nil { 21 if _, err = io.Copy(buf, f); err != nil {
21 return nil, err 22 return nil, err
22 } 23 }
23 24
24 return buf.Bytes(), nil 25 return buf.Bytes(), nil
25 } 26 }
26 27
27 // ReadFileLines ... 28 // ReadFileLines ...
28 func ReadFileLines(path string) ([]string, error) { 29 func ReadFileLines(path string) ([]string, error) {
29 f, err := os.Open(path) 30 f, err := os.Open(path)
30 if err != nil { 31 if err != nil {
31 return nil, err 32 return nil, err
32 } 33 }
33 defer f.Close() 34 defer f.Close()
34 35
35 var s strings.Builder 36 var s strings.Builder
36 37
37 if _, err = io.Copy(&s, f); err != nil { 38 if _, err = io.Copy(&s, f); err != nil {
38 return nil, err 39 return nil, err
39 } 40 }
40 41
41 lines := strings.Split(s.String(), "\n") 42 lines := strings.Split(s.String(), "\n")
42 for i := range lines { 43 for i := range lines {
43 lines[i] = strings.TrimRight(lines[i], "\r\n") 44 lines[i] = strings.TrimRight(lines[i], "\r\n")
44 } 45 }
45 46
46 return lines, nil 47 return lines, nil
47 } 48 }
48 49
49 // LinesToFile ... 50 // LinesToFile ...
50 func LinesToFile(path string, lines []string) error { 51 func LinesToFile(path string, lines []string) error {
51 content := "" 52 content := ""
52 for _, l := range lines { 53 for _, l := range lines {
53 content += l + "\n" 54 content += l + "\n"
54 } 55 }
55 56
56 return ioutil.WriteFile(path, []byte(content), 0644) // drw-r--r-- 57 return ioutil.WriteFile(path, []byte(content), 0644) // drw-r--r--
57 } 58 }
58 59
59 // InsertLine ... 60 // InsertLine ...
60 func InsertLine(lines *[]string, pos int64, l string) { 61 func InsertLine(lines *[]string, pos int64, l string) {
61 tail := append([]string{l}, (*lines)[pos:]...) 62 tail := append([]string{l}, (*lines)[pos:]...)
62 63
63 *lines = append((*lines)[:pos], tail...) 64 *lines = append((*lines)[:pos], tail...)
64 } 65 }
65 66
66 func WriteFile(path string, content []byte) error { 67 func WriteFile(path string, content []byte) error {
67 return ioutil.WriteFile(path, content, 0644) // drw-r--r-- 68 return ioutil.WriteFile(path, content, 0644) // drw-r--r--
68 } 69 }
69 70
70 func ListDir(path string) (fnames []string, err error) { 71 func ListDir(path string) (fnames []string, err error) {
71 finfo, err := ioutil.ReadDir(path) 72 finfo, err := ioutil.ReadDir(path)
72 if err != nil { 73 if err != nil {
73 return nil, err 74 return nil, err
74 } 75 }
75 76
76 for _, f := range finfo { 77 for _, f := range finfo {
77 fnames = append(fnames, f.Name()) 78 fnames = append(fnames, f.Name())
78 } 79 }
79 80
80 return fnames, nil 81 return fnames, nil
81 } 82 }
82 83
83 func WorkingDir() string { 84 func WorkingDir() string {
84 dir, _ := os.Getwd() 85 path, err := os.Getwd()
86 if err != nil {
87 fmt.Printf("couldn't get working directory: %s\n", err.Error())
88 }
89 return path
90 }
91
92 func FileExtension(path string) string {
93 parts := strings.Split(path, ".") // because name can contain dots
94 if len(parts) < 2 {
95 return ""
96 }
97 return "." + parts[len(parts)-1]
98 }
99
100 func DeleteFile(path string) error {
101 return os.Remove(path)
102 }
103
104 // DirectoryFromPath ...
105 func DirectoryFromPath(path string) (dir string) {
106 parts := strings.Split(path, "/")
107 if len(parts) == 1 {
108 return ""
109 }
110
111 dir = parts[0]
112 for _, p := range parts[1 : len(parts)-1] {
113 dir += "/" + p
114 }
115
85 return dir 116 return dir
86 } 117 }
118
119 // FileExists ...
120 func FileExists(path string) bool {
121 temp, err := os.Open(path)
122 defer temp.Close()
123
124 if err != nil {
125 return false
126 }
127
128 return true
129 }
87 130
1 package webutility 1 package webutility
2 2
3 import ( 3 import (
4 "fmt" 4 "fmt"
5 "math" 5 "math"
6 "math/big" 6 "math/big"
7 "strings" 7 "strings"
8 ) 8 )
9 9
10 func RoundFloat64(f float64, dec int) float64 { 10 func RoundFloat64(f float64, dec int) float64 {
11 p := math.Pow(10, float64(dec)) 11 p := math.Pow(10, float64(dec))
12 return math.Round(f*p) / p 12 return math.Round(f*p) / p
13 } 13 }
14 14
15 func NewBF(f float64, prec uint) *big.Float { 15 func NewBF(f float64, prec uint) *big.Float {
16 x := big.NewFloat(f) 16 x := big.NewFloat(f)
17 x.SetPrec(prec) 17 x.SetPrec(prec)
18 return x 18 return x
19 } 19 }
20 20
21 func AddBF(x, y *big.Float) *big.Float { 21 func AddBF(x, y *big.Float) *big.Float {
22 z := big.NewFloat(0.0) 22 z := big.NewFloat(0.0)
23 z.SetPrec(x.Prec()) 23 z.SetPrec(x.Prec())
24 z.Add(x, y) 24 z.Add(x, y)
25 return z 25 return z
26 } 26 }
27 27
28 func SubBF(x, y *big.Float) *big.Float { 28 func SubBF(x, y *big.Float) *big.Float {
29 z := big.NewFloat(0.0) 29 z := big.NewFloat(0.0)
30 z.SetPrec(x.Prec()) 30 z.SetPrec(x.Prec())
31 31
32 yneg := big.NewFloat(0.0) 32 yneg := big.NewFloat(0.0)
33 yneg.Neg(y) 33 yneg.Neg(y)
34 34
35 z.Add(x, yneg) 35 z.Add(x, yneg)
36 return z 36 return z
37 } 37 }
38 38
39 func MulBF(x, y *big.Float) *big.Float { 39 func MulBF(x, y *big.Float) *big.Float {
40 z := big.NewFloat(0.0) 40 z := big.NewFloat(0.0)
41 z.SetPrec(x.Prec()) 41 z.SetPrec(x.Prec())
42 z.Mul(x, y) 42 z.Mul(x, y)
43 return z 43 return z
44 } 44 }
45 45
46 func DivBF(x, y *big.Float) *big.Float { 46 func DivBF(x, y *big.Float) *big.Float {
47 z := big.NewFloat(0.0) 47 z := big.NewFloat(0.0)
48 z.SetPrec(x.Prec()) 48 z.SetPrec(x.Prec())
49 z.Quo(x, y) 49 z.Quo(x, y)
50 return z 50 return z
51 } 51 }
52 52
53 func BFtoFloat(f *big.Float) float64 { 53 func BFtoFloat(f *big.Float) float64 {
54 v, _ := f.Float64() 54 v, _ := f.Float64()
55 return v 55 return v
56 } 56 }
57 57
58 func Float64ToString(f float64) string { 58 func Float64ToString(f float64) string {
59 return fmt.Sprintf("%.2f", f) 59 return fmt.Sprintf("%.2f", f)
60 } 60 }
61 61
62 func Float64PtrToString(f *float64) string { 62 func Float64PtrToString(f *float64) string {
63 if f == nil { 63 if f == nil {
64 return "" 64 return ""
65 } 65 }
66 return fmt.Sprintf("%.2f", *f) 66 return fmt.Sprintf("%.2f", *f)
67 } 67 }
68 68
69 func FormatFloat64Number(f float64, dec int) string { 69 func FormatFloat64Number(f float64, dec int) string {
70 res := "" 70 res := ""
71 71
72 f = RoundFloat64(f, dec) 72 f = RoundFloat64(f, dec)
73 73
74 i := int64(f) 74 i := int64(f)
75 75
76 format := fmt.Sprintf("%%.%df", dec) 76 format := fmt.Sprintf("%%.%df", dec)
77 parts := strings.Split(fmt.Sprintf(format, f-float64(i)), ".") 77 parts := strings.Split(fmt.Sprintf(format, f-float64(i)), ".")
78 78
79 decimals := parts[1] 79 decimals := parts[1]
80 80
81 res = FormatInt64Number(i) + "," + decimals 81 res = FormatInt64Number(i) + "," + decimals
82 82
83 return res 83 return res
84 } 84 }
85
86 func MaxFlaot64(vars ...float64) (max float64) {
87 max = vars[0]
88 for _, v := range vars {
89 if v > max {
90 max = v
91 }
92 }
93 return max
94 }
85 95
1 package webutility 1 package webutility
2 2
3 import ( 3 import (
4 "database/sql" 4 "database/sql"
5 "fmt" 5 "fmt"
6 "net/http" 6 "net/http"
7 7
8 "git.to-net.rs/marko.tikvic/gologger" 8 "git.to-net.rs/marko.tikvic/gologger"
9 "github.com/gorilla/mux" 9 "github.com/gorilla/mux"
10 ) 10 )
11 11
12 type Server struct { 12 type Server struct {
13 DB *sql.DB 13 DB *sql.DB
14 Router *mux.Router 14 Router *mux.Router
15 Logger *gologger.Logger 15 Logger *gologger.Logger
16 Port string 16 Port string
17 UTCOffset int64 17 UTCOffset int64
18 DBs map[string]*sql.DB
18 } 19 }
19 20
20 func NewODBCServer(dsn, port, logDir string, utcOffset int64) (s *Server, err error) { 21 func NewODBCServer(dsn, port, logDir string, utcOffset int64) (s *Server, err error) {
21 s = new(Server) 22 s = new(Server)
22 23
23 s.Port = port 24 s.Port = port
24 25
25 if s.DB, err = sql.Open("odbc", fmt.Sprintf("DSN=%s;", dsn)); err != nil { 26 if s.DB, err = sql.Open("odbc", fmt.Sprintf("DSN=%s;", dsn)); err != nil {
26 return nil, err 27 return nil, err
27 } 28 }
28 29
29 s.Router = mux.NewRouter() 30 s.Router = mux.NewRouter()
30 31
31 if s.Logger, err = gologger.New("err", logDir, gologger.MaxLogSize1MB); err != nil { 32 if s.Logger, err = gologger.New("err", logDir, gologger.MaxLogSize1MB); err != nil {
32 return nil, fmt.Errorf("can't create logger: %s", err.Error()) 33 return nil, fmt.Errorf("can't create logger: %s", err.Error())
33 } 34 }
34 35
35 s.UTCOffset = utcOffset 36 s.UTCOffset = utcOffset
36 37
38 s.DBs = make(map[string]*sql.DB)
39 s.DBs["default"] = s.DB
40
37 return s, nil 41 return s, nil
38 } 42 }
39 43
40 func (s *Server) Run() { 44 func (s *Server) Run() {
41 s.Logger.Print("Server listening on %s", s.Port) 45 s.Logger.Print("Server listening on %s", s.Port)
42 s.Logger.PrintAndTrace(http.ListenAndServe(s.Port, s.Router).Error()) 46 s.Logger.PrintAndTrace(http.ListenAndServe(s.Port, s.Router).Error())
43 } 47 }
44 48
45 func (s *Server) Cleanup() { 49 func (s *Server) Cleanup() {
46 if s.DB != nil { 50 if s.DB != nil {
47 s.DB.Close() 51 s.DB.Close()
48 } 52 }
49 53
50 if s.Logger != nil { 54 if s.Logger != nil {
51 s.Logger.Close() 55 s.Logger.Close()
52 } 56 }
53 } 57 }
54 58
55 func (s *Server) StartTransaction() (*sql.Tx, error) { 59 func (s *Server) StartTransaction() (*sql.Tx, error) {
56 return s.DB.Begin() 60 return s.DB.Begin()
57 } 61 }
58 62
59 func CommitChanges(tx *sql.Tx, err *error, opt ...error) { 63 func CommitChanges(tx *sql.Tx, err *error, opt ...error) {
60 if *err != nil { 64 if *err != nil {
61 tx.Rollback() 65 tx.Rollback()
62 return 66 return
63 } 67 }
64 68
65 for _, e := range opt { 69 for _, e := range opt {
66 if e != nil { 70 if e != nil {
67 tx.Rollback() 71 tx.Rollback()
68 return 72 return
69 } 73 }
70 } 74 }
71 75
72 if *err = tx.Commit(); *err != nil { 76 if *err = tx.Commit(); *err != nil {
73 tx.Rollback() 77 tx.Rollback()
74 } 78 }
75 } 79 }
76 80