mongodao.go 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449
  1. package dao
  2. import (
  3. "context"
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. "io"
  8. "io/ioutil"
  9. "log"
  10. "os"
  11. "sort"
  12. "strings"
  13. "time"
  14. "github.com/willie68/schematic-service-go/config"
  15. slicesutils "github.com/willie68/schematic-service-go/internal"
  16. "github.com/willie68/schematic-service-go/model"
  17. "go.mongodb.org/mongo-driver/bson"
  18. "go.mongodb.org/mongo-driver/bson/primitive"
  19. "go.mongodb.org/mongo-driver/mongo"
  20. "go.mongodb.org/mongo-driver/mongo/gridfs"
  21. "go.mongodb.org/mongo-driver/mongo/options"
  22. )
  23. // time to reload all users
  24. const userReloadPeriod = 1 * time.Hour
  25. const timeout = 1 * time.Minute
  26. const attachmentsCollectionName = "attachments"
  27. const schematicsCollectionName = "schematics"
  28. const tagsCollectionName = "tags"
  29. const manufacturersCollectionName = "manufacturers"
  30. const usersCollectionName = "users"
  31. const effectsCollectionName = "effects"
  32. const effectTypesCollectionName = "effectTypes"
  33. // MongoDAO a mongodb based dao
  34. type MongoDAO struct {
  35. initialised bool
  36. client *mongo.Client
  37. mongoConfig config.MongoDB
  38. bucket gridfs.Bucket
  39. database mongo.Database
  40. tags model.Tags
  41. manufacturers model.Manufacturers
  42. users map[string]string
  43. ticker time.Ticker
  44. done chan bool
  45. }
  46. // InitDAO initialise the mongodb connection, build up all collections and indexes
  47. func (m *MongoDAO) InitDAO(MongoConfig config.MongoDB) {
  48. m.initialised = false
  49. m.mongoConfig = MongoConfig
  50. // uri := fmt.Sprintf("mongodb://%s:%s@%s:%d", mongoConfig.Username, mongoConfig.Password, mongoConfig.Host, mongoConfig.Port)
  51. uri := fmt.Sprintf("mongodb://%s:%d", m.mongoConfig.Host, m.mongoConfig.Port)
  52. clientOptions := options.Client()
  53. clientOptions.ApplyURI(uri)
  54. clientOptions.Auth = &options.Credential{Username: m.mongoConfig.Username, Password: m.mongoConfig.Password, AuthSource: m.mongoConfig.AuthDB}
  55. var err error
  56. m.client, err = mongo.NewClient(clientOptions)
  57. if err != nil {
  58. fmt.Printf("error: %s\n", err.Error())
  59. }
  60. ctx, cancel := context.WithTimeout(context.Background(), timeout)
  61. defer cancel()
  62. err = m.client.Connect(ctx)
  63. if err != nil {
  64. fmt.Printf("error: %s\n", err.Error())
  65. }
  66. m.database = *m.client.Database(m.mongoConfig.Database)
  67. myBucket, err := gridfs.NewBucket(&m.database, options.GridFSBucket().SetName(attachmentsCollectionName))
  68. if err != nil {
  69. fmt.Printf("error: %s\n", err.Error())
  70. }
  71. m.bucket = *myBucket
  72. m.initIndexSchematics()
  73. m.initIndexTags()
  74. m.initIndexManufacturers()
  75. m.initIndexEffectTypes()
  76. m.initIndexEffects()
  77. m.tags = model.NewTags()
  78. m.manufacturers = model.NewManufacturers()
  79. m.users = make(map[string]string)
  80. m.initTags()
  81. m.initManufacturers()
  82. m.initUsers()
  83. m.initialised = true
  84. }
  85. func (m *MongoDAO) initIndexSchematics() {
  86. collection := m.database.Collection(schematicsCollectionName)
  87. indexView := collection.Indexes()
  88. ctx, _ := context.WithTimeout(context.Background(), timeout)
  89. cursor, err := indexView.List(ctx)
  90. if err != nil {
  91. log.Fatal(err)
  92. }
  93. defer cursor.Close(ctx)
  94. myIndexes := make([]string, 0)
  95. for cursor.Next(ctx) {
  96. var index bson.M
  97. if err = cursor.Decode(&index); err != nil {
  98. log.Fatal(err)
  99. }
  100. myIndexes = append(myIndexes, index["name"].(string))
  101. }
  102. if !slicesutils.Contains(myIndexes, "manufacturer") {
  103. ctx, _ = context.WithTimeout(context.Background(), timeout)
  104. models := []mongo.IndexModel{
  105. {
  106. Keys: bson.D{{"manufacturer", 1}},
  107. Options: options.Index().SetName("manufacturer").SetCollation(&options.Collation{Locale: "en", Strength: 2}),
  108. },
  109. {
  110. Keys: bson.D{{"model", 1}},
  111. Options: options.Index().SetName("model").SetCollation(&options.Collation{Locale: "en", Strength: 2}),
  112. },
  113. {
  114. Keys: bson.D{{"tags", 1}},
  115. Options: options.Index().SetName("tags").SetCollation(&options.Collation{Locale: "en", Strength: 2}),
  116. },
  117. {
  118. Keys: bson.D{{"subtitle", 1}},
  119. Options: options.Index().SetName("subtitle").SetCollation(&options.Collation{Locale: "en", Strength: 2}),
  120. },
  121. {
  122. Keys: bson.D{{"manufacturer", "text"}, {"model", "text"}, {"tags", "text"}, {"subtitle", "text"}, {"description", "text"}, {"owner", "text"}},
  123. Options: options.Index().SetName("$text"),
  124. },
  125. }
  126. // Specify the MaxTime option to limit the amount of time the operation can run on the server
  127. opts := options.CreateIndexes().SetMaxTime(2 * time.Second)
  128. names, err := indexView.CreateMany(context.TODO(), models, opts)
  129. if err != nil {
  130. log.Fatal(err)
  131. }
  132. log.Print("create indexes:")
  133. for _, name := range names {
  134. log.Println(name)
  135. }
  136. }
  137. }
  138. func (m *MongoDAO) initIndexTags() {
  139. collection := m.database.Collection(tagsCollectionName)
  140. indexView := collection.Indexes()
  141. ctx, _ := context.WithTimeout(context.Background(), timeout)
  142. cursor, err := indexView.List(ctx)
  143. if err != nil {
  144. log.Fatal(err)
  145. }
  146. defer cursor.Close(ctx)
  147. myIndexes := make([]string, 0)
  148. for cursor.Next(ctx) {
  149. var index bson.M
  150. if err = cursor.Decode(&index); err != nil {
  151. log.Fatal(err)
  152. }
  153. myIndexes = append(myIndexes, index["name"].(string))
  154. }
  155. if !slicesutils.Contains(myIndexes, "name") {
  156. ctx, _ = context.WithTimeout(context.Background(), timeout)
  157. models := []mongo.IndexModel{
  158. {
  159. Keys: bson.D{{"name", 1}},
  160. Options: options.Index().SetUnique(true).SetName("name").SetCollation(&options.Collation{Locale: "en", Strength: 2}),
  161. },
  162. }
  163. // Specify the MaxTime option to limit the amount of time the operation can run on the server
  164. opts := options.CreateIndexes().SetMaxTime(2 * time.Second)
  165. names, err := indexView.CreateMany(context.TODO(), models, opts)
  166. if err != nil {
  167. log.Fatal(err)
  168. }
  169. log.Print("create indexes:")
  170. for _, name := range names {
  171. log.Println(name)
  172. }
  173. }
  174. }
  175. func (m *MongoDAO) initIndexManufacturers() {
  176. collection := m.database.Collection(manufacturersCollectionName)
  177. indexView := collection.Indexes()
  178. ctx, _ := context.WithTimeout(context.Background(), timeout)
  179. cursor, err := indexView.List(ctx)
  180. if err != nil {
  181. log.Fatal(err)
  182. }
  183. defer cursor.Close(ctx)
  184. myIndexes := make([]string, 0)
  185. for cursor.Next(ctx) {
  186. var index bson.M
  187. if err = cursor.Decode(&index); err != nil {
  188. log.Fatal(err)
  189. }
  190. myIndexes = append(myIndexes, index["name"].(string))
  191. }
  192. if !slicesutils.Contains(myIndexes, "name") {
  193. ctx, _ = context.WithTimeout(context.Background(), timeout)
  194. models := []mongo.IndexModel{
  195. {
  196. Keys: bson.D{{"name", 1}},
  197. Options: options.Index().SetUnique(true).SetName("name").SetCollation(&options.Collation{Locale: "en", Strength: 2}),
  198. },
  199. }
  200. // Specify the MaxTime option to limit the amount of time the operation can run on the server
  201. opts := options.CreateIndexes().SetMaxTime(2 * time.Second)
  202. names, err := indexView.CreateMany(context.TODO(), models, opts)
  203. if err != nil {
  204. log.Fatal(err)
  205. }
  206. log.Print("create indexes:")
  207. for _, name := range names {
  208. log.Println(name)
  209. }
  210. }
  211. }
  212. func (m *MongoDAO) initIndexEffects() {
  213. collection := m.database.Collection(effectsCollectionName)
  214. indexView := collection.Indexes()
  215. ctx, _ := context.WithTimeout(context.Background(), timeout)
  216. cursor, err := indexView.List(ctx)
  217. if err != nil {
  218. log.Fatal(err)
  219. }
  220. defer cursor.Close(ctx)
  221. myIndexes := make([]string, 0)
  222. for cursor.Next(ctx) {
  223. var index bson.M
  224. if err = cursor.Decode(&index); err != nil {
  225. log.Fatal(err)
  226. }
  227. myIndexes = append(myIndexes, index["name"].(string))
  228. }
  229. if !slicesutils.Contains(myIndexes, "effectType") {
  230. ctx, _ = context.WithTimeout(context.Background(), timeout)
  231. models := []mongo.IndexModel{
  232. {
  233. Keys: bson.D{{"effectType", 1}},
  234. Options: options.Index().SetName("effectType").SetCollation(&options.Collation{Locale: "en", Strength: 2}),
  235. },
  236. {
  237. Keys: bson.D{{"manufacturer", 1}},
  238. Options: options.Index().SetName("manufacturer").SetCollation(&options.Collation{Locale: "en", Strength: 2}),
  239. },
  240. {
  241. Keys: bson.D{{"model", 1}},
  242. Options: options.Index().SetName("model").SetCollation(&options.Collation{Locale: "en", Strength: 2}),
  243. },
  244. {
  245. Keys: bson.D{{"tags", 1}},
  246. Options: options.Index().SetName("tags").SetCollation(&options.Collation{Locale: "en", Strength: 2}),
  247. },
  248. {
  249. Keys: bson.D{{"comment", 1}},
  250. Options: options.Index().SetName("comment").SetCollation(&options.Collation{Locale: "en", Strength: 2}),
  251. },
  252. {
  253. Keys: bson.D{{"effectType", "text"}, {"manufacturer", "text"}, {"model", "text"}, {"tags", "text"}, {"comment", "text"}, {"connector", "text"}, {"current", "text"}, {"voltage", "text"}},
  254. Options: options.Index().SetName("$text"),
  255. },
  256. }
  257. // Specify the MaxTime option to limit the amount of time the operation can run on the server
  258. opts := options.CreateIndexes().SetMaxTime(2 * time.Second)
  259. names, err := indexView.CreateMany(context.TODO(), models, opts)
  260. if err != nil {
  261. log.Fatal(err)
  262. }
  263. log.Print("create indexes:")
  264. for _, name := range names {
  265. log.Println(name)
  266. }
  267. }
  268. }
  269. func (m *MongoDAO) initIndexEffectTypes() {
  270. collection := m.database.Collection(effectTypesCollectionName)
  271. indexView := collection.Indexes()
  272. ctx, _ := context.WithTimeout(context.Background(), timeout)
  273. cursor, err := indexView.List(ctx)
  274. if err != nil {
  275. log.Fatal(err)
  276. }
  277. defer cursor.Close(ctx)
  278. myIndexes := make([]string, 0)
  279. for cursor.Next(ctx) {
  280. var index bson.M
  281. if err = cursor.Decode(&index); err != nil {
  282. log.Fatal(err)
  283. }
  284. myIndexes = append(myIndexes, index["name"].(string))
  285. }
  286. if !slicesutils.Contains(myIndexes, "typeName") {
  287. ctx, _ = context.WithTimeout(context.Background(), timeout)
  288. models := []mongo.IndexModel{
  289. {
  290. Keys: bson.D{{"typeName", 1}},
  291. Options: options.Index().SetName("typeName").SetCollation(&options.Collation{Locale: "en", Strength: 2}),
  292. },
  293. }
  294. // Specify the MaxTime option to limit the amount of time the operation can run on the server
  295. opts := options.CreateIndexes().SetMaxTime(2 * time.Second)
  296. names, err := indexView.CreateMany(context.TODO(), models, opts)
  297. if err != nil {
  298. log.Fatal(err)
  299. }
  300. log.Print("create indexes:")
  301. for _, name := range names {
  302. log.Println(name)
  303. }
  304. }
  305. }
  306. func (m *MongoDAO) initTags() {
  307. m.reloadTags()
  308. }
  309. func (m *MongoDAO) initManufacturers() {
  310. m.reloadManufacturers()
  311. }
  312. func (m *MongoDAO) initUsers() {
  313. m.reloadUsers()
  314. go func() {
  315. background := time.NewTicker(userReloadPeriod)
  316. for _ = range background.C {
  317. m.reloadUsers()
  318. m.reloadTags()
  319. m.reloadManufacturers()
  320. }
  321. }()
  322. }
  323. func (m *MongoDAO) reloadUsers() {
  324. ctx, _ := context.WithTimeout(context.Background(), timeout)
  325. usersCollection := m.database.Collection(usersCollectionName)
  326. cursor, err := usersCollection.Find(ctx, bson.M{})
  327. if err != nil {
  328. log.Fatal(err)
  329. }
  330. defer cursor.Close(ctx)
  331. localUsers := make(map[string]string)
  332. for cursor.Next(ctx) {
  333. var user bson.M
  334. if err = cursor.Decode(&user); err != nil {
  335. log.Fatal(err)
  336. } else {
  337. username := strings.ToLower(user["name"].(string))
  338. password := user["password"].(string)
  339. localUsers[username] = BuildPasswordHash(password)
  340. }
  341. }
  342. m.users = localUsers
  343. if len(m.users) == 0 {
  344. admin := model.User{
  345. Name: "w.klaas@gmx.de",
  346. Password: "akteon0000",
  347. Admin: true,
  348. }
  349. m.AddUser(admin)
  350. guest := model.User{
  351. Name: "gast",
  352. Password: "gast1234",
  353. Admin: false,
  354. Guest: true,
  355. }
  356. m.AddUser(guest)
  357. }
  358. }
  359. func (m *MongoDAO) reloadTags() {
  360. myTags := model.NewTags()
  361. ctx, _ := context.WithTimeout(context.Background(), timeout)
  362. tagsCollection := m.database.Collection(tagsCollectionName)
  363. cursor, err := tagsCollection.Find(ctx, bson.M{})
  364. if err != nil {
  365. log.Fatal(err)
  366. }
  367. defer cursor.Close(ctx)
  368. tagList := make([]string, 0)
  369. for cursor.Next(ctx) {
  370. var tag bson.M
  371. if err = cursor.Decode(&tag); err != nil {
  372. log.Fatal(err)
  373. } else {
  374. tagList = append(tagList, tag["name"].(string))
  375. }
  376. }
  377. ctx, _ = context.WithTimeout(context.Background(), timeout)
  378. schematicCollection := m.database.Collection(schematicsCollectionName)
  379. for _, tagName := range tagList {
  380. queryDoc := bson.M{
  381. "tags": tagName,
  382. }
  383. n, err := schematicCollection.CountDocuments(ctx, queryDoc, &options.CountOptions{Collation: &options.Collation{Locale: "en", Strength: 2}})
  384. if err != nil {
  385. log.Println(err)
  386. }
  387. //log.Printf("tag: %s has %d schematics.", tagName, n)
  388. myTags.Add(tagName, int(n))
  389. }
  390. m.tags = myTags
  391. }
  392. func (m *MongoDAO) reloadManufacturers() {
  393. myManufacturer := model.NewManufacturers()
  394. ctx, _ := context.WithTimeout(context.Background(), timeout)
  395. manufacturersCollection := m.database.Collection(manufacturersCollectionName)
  396. cursor, err := manufacturersCollection.Find(ctx, bson.M{})
  397. if err != nil {
  398. log.Fatal(err)
  399. }
  400. defer cursor.Close(ctx)
  401. manuList := make([]string, 0)
  402. for cursor.Next(ctx) {
  403. var manufacturer bson.M
  404. if err = cursor.Decode(&manufacturer); err != nil {
  405. log.Fatal(err)
  406. } else {
  407. manuList = append(manuList, manufacturer["name"].(string))
  408. }
  409. }
  410. ctx, _ = context.WithTimeout(context.Background(), timeout)
  411. schematicCollection := m.database.Collection(schematicsCollectionName)
  412. for _, manuName := range manuList {
  413. queryDoc := bson.M{
  414. "manufacturer": manuName,
  415. }
  416. n, err := schematicCollection.CountDocuments(ctx, queryDoc, &options.CountOptions{Collation: &options.Collation{Locale: "en", Strength: 2}})
  417. if err != nil {
  418. log.Println(err)
  419. }
  420. //log.Printf("manufacturer: %s has %d schematics.", manuName, n)
  421. myManufacturer.Add(manuName, int(n))
  422. }
  423. m.manufacturers = myManufacturer
  424. }
  425. // AddFile adding a file to the storage, stream like
  426. func (m *MongoDAO) AddFile(filename string, reader io.Reader) (string, error) {
  427. uploadOpts := options.GridFSUpload().SetMetadata(bson.D{{"tag", "tag"}})
  428. fileID, err := m.bucket.UploadFromStream(filename, reader, uploadOpts)
  429. if err != nil {
  430. fmt.Printf("error: %s\n", err.Error())
  431. return "", err
  432. }
  433. log.Printf("Write file to DB was successful. File id: %s \n", fileID)
  434. id := fileID.Hex()
  435. return id, nil
  436. }
  437. // CreateSchematic creating a new schematic in the database
  438. func (m *MongoDAO) CreateSchematic(schematic model.Schematic) (string, error) {
  439. for _, tag := range schematic.Tags {
  440. if !m.tags.Contains(tag) {
  441. m.CreateTag(tag)
  442. }
  443. }
  444. if !m.manufacturers.Contains(schematic.Manufacturer) {
  445. m.CreateManufacturer(schematic.Manufacturer)
  446. }
  447. ctx, _ := context.WithTimeout(context.Background(), timeout)
  448. collection := m.database.Collection(schematicsCollectionName)
  449. result, err := collection.InsertOne(ctx, schematic)
  450. if err != nil {
  451. fmt.Printf("error: %s\n", err.Error())
  452. return "", err
  453. }
  454. filter := bson.M{"_id": result.InsertedID}
  455. err = collection.FindOne(ctx, filter).Decode(&schematic)
  456. if err != nil {
  457. fmt.Printf("error: %s\n", err.Error())
  458. return "", err
  459. }
  460. switch v := result.InsertedID.(type) {
  461. case primitive.ObjectID:
  462. return v.Hex(), nil
  463. }
  464. return "", nil
  465. }
  466. // UpdateSchematic creating a new schematic in the database
  467. func (m *MongoDAO) UpdateSchematic(schematic model.Schematic) (string, error) {
  468. for _, tag := range schematic.Tags {
  469. if !m.tags.Contains(tag) {
  470. m.CreateTag(tag)
  471. }
  472. }
  473. if !m.manufacturers.Contains(schematic.Manufacturer) {
  474. m.CreateManufacturer(schematic.Manufacturer)
  475. }
  476. ctx, _ := context.WithTimeout(context.Background(), timeout)
  477. collection := m.database.Collection(schematicsCollectionName)
  478. filter := bson.M{"_id": schematic.ID}
  479. updateDoc := bson.D{{"$set", schematic}}
  480. result, err := collection.UpdateOne(ctx, filter, updateDoc)
  481. if err != nil {
  482. fmt.Printf("error: %s\n", err.Error())
  483. return "", err
  484. }
  485. if result.ModifiedCount != 1 {
  486. return "", errors.New("can't update document.")
  487. }
  488. err = collection.FindOne(ctx, filter).Decode(&schematic)
  489. if err != nil {
  490. fmt.Printf("error: %s\n", err.Error())
  491. return "", err
  492. }
  493. return schematic.ID.Hex(), nil
  494. }
  495. // GetSchematic getting a sdingle schematic
  496. func (m *MongoDAO) GetSchematic(schematicID string) (model.Schematic, error) {
  497. ctx, _ := context.WithTimeout(context.Background(), timeout)
  498. schematicCollection := m.database.Collection(schematicsCollectionName)
  499. objectID, _ := primitive.ObjectIDFromHex(schematicID)
  500. result := schematicCollection.FindOne(ctx, bson.M{"_id": objectID})
  501. err := result.Err()
  502. if err == mongo.ErrNoDocuments {
  503. log.Print(err)
  504. return model.Schematic{}, ErrNoDocument
  505. }
  506. if err != nil {
  507. log.Print(err)
  508. return model.Schematic{}, err
  509. }
  510. var schematic model.Schematic
  511. if err := result.Decode(&schematic); err != nil {
  512. log.Print(err)
  513. return model.Schematic{}, err
  514. } else {
  515. return schematic, nil
  516. }
  517. }
  518. // DeleteSchematic getting a sdingle schematic
  519. func (m *MongoDAO) DeleteSchematic(schematicID string) error {
  520. ctx, _ := context.WithTimeout(context.Background(), timeout)
  521. schematicCollection := m.database.Collection(schematicsCollectionName)
  522. objectID, _ := primitive.ObjectIDFromHex(schematicID)
  523. result, err := schematicCollection.DeleteOne(ctx, bson.M{"_id": objectID})
  524. if err != nil {
  525. log.Print(err)
  526. return err
  527. } else {
  528. if result.DeletedCount > 0 {
  529. return nil
  530. }
  531. return ErrNoDocument
  532. }
  533. }
  534. //GetFile getting a single from the database with the id
  535. func (m *MongoDAO) GetFilename(fileid string) (string, error) {
  536. objectID, err := primitive.ObjectIDFromHex(fileid)
  537. if err != nil {
  538. log.Print(err)
  539. return "", err
  540. }
  541. ctx, _ := context.WithTimeout(context.Background(), timeout)
  542. cursor, err := m.bucket.Find(bson.M{"_id": objectID})
  543. if err != nil {
  544. log.Print(err)
  545. return "", err
  546. }
  547. defer cursor.Close(ctx)
  548. cursor.Next(ctx)
  549. var file bson.M
  550. var filename string
  551. if err = cursor.Decode(&file); err != nil {
  552. log.Print(err)
  553. return "", err
  554. } else {
  555. filename = file["filename"].(string)
  556. }
  557. return filename, nil
  558. }
  559. //GetFile getting a single from the database with the id
  560. func (m *MongoDAO) GetFile(fileid string, stream io.Writer) error {
  561. objectID, err := primitive.ObjectIDFromHex(fileid)
  562. if err != nil {
  563. log.Print(err)
  564. return err
  565. }
  566. _, err = m.bucket.DownloadToStream(objectID, stream)
  567. if err != nil {
  568. log.Print(err)
  569. return err
  570. }
  571. return nil
  572. }
  573. // GetSchematics getting a sdingle schematic
  574. func (m *MongoDAO) GetSchematics(query string, offset int, limit int, owner string) (int64, []model.Schematic, error) {
  575. ctx, _ := context.WithTimeout(context.Background(), timeout)
  576. schematicCollection := m.database.Collection(schematicsCollectionName)
  577. var queryM map[string]interface{}
  578. err := json.Unmarshal([]byte(query), &queryM)
  579. if err != nil {
  580. log.Print(err)
  581. return 0, nil, err
  582. }
  583. queryDoc := bson.M{}
  584. for k, v := range queryM {
  585. if k == "$fulltext" {
  586. queryDoc["$text"] = bson.M{"$search": v}
  587. } else {
  588. switch v := v.(type) {
  589. // case float64:
  590. // case int:
  591. // case bool:
  592. case string:
  593. queryDoc[k] = bson.M{"$regex": v}
  594. }
  595. //queryDoc[k] = v
  596. }
  597. }
  598. data, _ := json.Marshal(queryDoc)
  599. log.Printf("mongoquery: %s\n", string(data))
  600. n, err := schematicCollection.CountDocuments(ctx, queryDoc, &options.CountOptions{Collation: &options.Collation{Locale: "en", Strength: 2}})
  601. if err != nil {
  602. log.Print(err)
  603. return 0, nil, err
  604. }
  605. cursor, err := schematicCollection.Find(ctx, queryDoc, &options.FindOptions{Collation: &options.Collation{Locale: "en", Strength: 2}})
  606. if err != nil {
  607. log.Print(err)
  608. return 0, nil, err
  609. }
  610. defer cursor.Close(ctx)
  611. schematics := make([]model.Schematic, 0)
  612. count := 0
  613. docs := 0
  614. for cursor.Next(ctx) {
  615. if count >= offset {
  616. if docs < limit {
  617. var schematic model.Schematic
  618. if err = cursor.Decode(&schematic); err != nil {
  619. log.Print(err)
  620. return 0, nil, err
  621. } else {
  622. if !schematic.PrivateFile || schematic.Owner == owner {
  623. schematics = append(schematics, schematic)
  624. docs++
  625. }
  626. }
  627. } else {
  628. break
  629. }
  630. }
  631. count++
  632. }
  633. return n, schematics, nil
  634. }
  635. // GetSchematicsCount getting a sdingle schematic
  636. func (m *MongoDAO) GetSchematicsCount(query string, owner string) (int64, error) {
  637. ctx, _ := context.WithTimeout(context.Background(), timeout)
  638. schematicCollection := m.database.Collection(schematicsCollectionName)
  639. queryDoc := bson.M{}
  640. if query != "" {
  641. var queryM map[string]interface{}
  642. err := json.Unmarshal([]byte(query), &queryM)
  643. if err != nil {
  644. log.Print(err)
  645. return 0, err
  646. }
  647. for k, v := range queryM {
  648. if k == "$fulltext" {
  649. queryDoc["$text"] = bson.M{"$search": v}
  650. } else {
  651. switch v := v.(type) {
  652. // case float64:
  653. // case int:
  654. // case bool:
  655. case string:
  656. queryDoc[k] = bson.M{"$regex": v}
  657. }
  658. //queryDoc[k] = v
  659. }
  660. }
  661. data, _ := json.Marshal(queryDoc)
  662. log.Printf("mongoquery: %s\n", string(data))
  663. }
  664. n, err := schematicCollection.CountDocuments(ctx, queryDoc, &options.CountOptions{Collation: &options.Collation{Locale: "en", Strength: 2}})
  665. if err != nil {
  666. log.Print(err)
  667. return 0, err
  668. }
  669. return n, nil
  670. }
  671. // CreateTag create a new tag in the storage
  672. func (m *MongoDAO) CreateTag(tag string) error {
  673. tag = strings.ToLower(tag)
  674. ctx, _ := context.WithTimeout(context.Background(), timeout)
  675. collection := m.database.Collection(tagsCollectionName)
  676. tagModel := bson.M{"name": tag}
  677. _, err := collection.InsertOne(ctx, tagModel)
  678. if err != nil {
  679. fmt.Printf("error: %s\n", err.Error())
  680. return err
  681. }
  682. m.tags.Add(tag, 1)
  683. return nil
  684. }
  685. //GetTags getting a list of all tags
  686. func (m *MongoDAO) GetTags() []model.Tag {
  687. sort.Slice(m.tags.List, func(i, j int) bool { return m.tags.List[i].Name < m.tags.List[j].Name })
  688. return m.tags.List
  689. }
  690. // GetTagsCount getting the count of all tags
  691. func (m *MongoDAO) GetTagsCount() int {
  692. return len(m.tags.List)
  693. }
  694. // CreateManufacturer create a new manufacturer in the storage
  695. func (m *MongoDAO) CreateManufacturer(manufacturer string) error {
  696. ctx, _ := context.WithTimeout(context.Background(), timeout)
  697. collection := m.database.Collection(manufacturersCollectionName)
  698. manufacturerModel := bson.M{"name": manufacturer}
  699. _, err := collection.InsertOne(ctx, manufacturerModel)
  700. if err != nil {
  701. fmt.Printf("error: %s\n", err.Error())
  702. return err
  703. }
  704. m.manufacturers.Add(manufacturer, 1)
  705. return nil
  706. }
  707. // GetManufacturers getting a list of all manufacturers
  708. func (m *MongoDAO) GetManufacturers() []model.Manufacturer {
  709. sort.Slice(m.manufacturers.List, func(i, j int) bool { return m.manufacturers.List[i].Name < m.manufacturers.List[j].Name })
  710. return m.manufacturers.List
  711. }
  712. // GetManufacturersCount getting the count of all manufacturers
  713. func (m *MongoDAO) GetManufacturersCount() int {
  714. return len(m.manufacturers.List)
  715. }
  716. //CreateEffectType cerating a new effect type
  717. func (m *MongoDAO) CreateEffectType(effectType model.EffectType) (string, error) {
  718. ctx, _ := context.WithTimeout(context.Background(), timeout)
  719. collection := m.database.Collection(effectTypesCollectionName)
  720. result, err := collection.InsertOne(ctx, effectType)
  721. if err != nil {
  722. fmt.Printf("error: %s\n", err.Error())
  723. return "", err
  724. }
  725. filter := bson.M{"_id": result.InsertedID}
  726. err = collection.FindOne(ctx, filter).Decode(&effectType)
  727. if err != nil {
  728. fmt.Printf("error: %s\n", err.Error())
  729. return "", err
  730. }
  731. switch v := result.InsertedID.(type) {
  732. case primitive.ObjectID:
  733. return v.Hex(), nil
  734. }
  735. return "", nil
  736. }
  737. // GetEffectTypes getting a sdingle schematic
  738. func (m *MongoDAO) GetEffectTypes() ([]model.EffectType, error) {
  739. ctx, _ := context.WithTimeout(context.Background(), timeout)
  740. collection := m.database.Collection(effectTypesCollectionName)
  741. findOptions := options.Find()
  742. // Sort by `price` field descending
  743. findOptions.SetSort(bson.D{{"typeName", 1}})
  744. queryDoc := bson.M{}
  745. cursor, err := collection.Find(ctx, queryDoc, &options.FindOptions{Collation: &options.Collation{Locale: "en", Strength: 2}, Sort: bson.D{{"typeName", 1}}})
  746. if err != nil {
  747. log.Print(err)
  748. return nil, err
  749. }
  750. defer cursor.Close(ctx)
  751. effectTypes := make([]model.EffectType, 0)
  752. for cursor.Next(ctx) {
  753. var effectType model.EffectType
  754. if err = cursor.Decode(&effectType); err != nil {
  755. log.Print(err)
  756. return nil, err
  757. } else {
  758. effectTypes = append(effectTypes, effectType)
  759. }
  760. }
  761. return effectTypes, nil
  762. }
  763. //CreateEffect cerating a new effect type
  764. func (m *MongoDAO) CreateEffect(effect model.Effect) (string, error) {
  765. for _, tag := range effect.Tags {
  766. if !m.tags.Contains(tag) {
  767. m.CreateTag(tag)
  768. }
  769. }
  770. if !m.manufacturers.Contains(effect.Manufacturer) {
  771. m.CreateManufacturer(effect.Manufacturer)
  772. }
  773. ctx, _ := context.WithTimeout(context.Background(), timeout)
  774. collection := m.database.Collection(effectsCollectionName)
  775. result, err := collection.InsertOne(ctx, effect)
  776. if err != nil {
  777. fmt.Printf("error: %s\n", err.Error())
  778. return "", err
  779. }
  780. filter := bson.M{"_id": result.InsertedID}
  781. err = collection.FindOne(ctx, filter).Decode(&effect)
  782. if err != nil {
  783. fmt.Printf("error: %s\n", err.Error())
  784. return "", err
  785. }
  786. switch v := result.InsertedID.(type) {
  787. case primitive.ObjectID:
  788. return v.Hex(), nil
  789. }
  790. return "", nil
  791. }
  792. //GetEffectsCount getting the count of effects regarding to the query
  793. func (m *MongoDAO) GetEffectsCount(query string) (int, error) {
  794. ctx, _ := context.WithTimeout(context.Background(), timeout)
  795. collection := m.database.Collection(effectsCollectionName)
  796. queryDoc := bson.M{}
  797. if query != "" {
  798. var queryM map[string]interface{}
  799. err := json.Unmarshal([]byte(query), &queryM)
  800. if err != nil {
  801. log.Print(err)
  802. return 0, err
  803. }
  804. for k, v := range queryM {
  805. if k == "$fulltext" {
  806. queryDoc["$text"] = bson.M{"$search": v}
  807. } else {
  808. switch v := v.(type) {
  809. // case float64:
  810. // case int:
  811. // case bool:
  812. case string:
  813. queryDoc[k] = bson.M{"$regex": v}
  814. }
  815. //queryDoc[k] = v
  816. }
  817. }
  818. data, _ := json.Marshal(queryDoc)
  819. log.Printf("mongoquery: %s\n", string(data))
  820. }
  821. n, err := collection.CountDocuments(ctx, queryDoc, &options.CountOptions{Collation: &options.Collation{Locale: "en", Strength: 2}})
  822. if err != nil {
  823. log.Print(err)
  824. return 0, err
  825. }
  826. return int(n), nil
  827. }
  828. //GetEffects getting a list of effects regarding to the query
  829. func (m *MongoDAO) GetEffects(query string, offset int, limit int) (int, []model.Effect, error) {
  830. ctx, _ := context.WithTimeout(context.Background(), timeout)
  831. collection := m.database.Collection(effectsCollectionName)
  832. queryDoc := bson.M{}
  833. if query != "" {
  834. var queryM map[string]interface{}
  835. err := json.Unmarshal([]byte(query), &queryM)
  836. if err != nil {
  837. log.Print(err)
  838. return 0, nil, err
  839. }
  840. for k, v := range queryM {
  841. if k == "$fulltext" {
  842. queryDoc["$text"] = bson.M{"$search": v}
  843. } else {
  844. switch v := v.(type) {
  845. // case float64:
  846. // case int:
  847. // case bool:
  848. case string:
  849. queryDoc[k] = bson.M{"$regex": v}
  850. }
  851. //queryDoc[k] = v
  852. }
  853. }
  854. data, _ := json.Marshal(queryDoc)
  855. log.Printf("mongoquery: %s\n", string(data))
  856. }
  857. n, err := collection.CountDocuments(ctx, queryDoc, &options.CountOptions{Collation: &options.Collation{Locale: "en", Strength: 2}})
  858. if err != nil {
  859. log.Print(err)
  860. return 0, nil, err
  861. }
  862. cursor, err := collection.Find(ctx, queryDoc, &options.FindOptions{Collation: &options.Collation{Locale: "en", Strength: 2}, Sort: bson.D{{"manufacturer", 1}, {"model", 1}}})
  863. if err != nil {
  864. log.Print(err)
  865. return 0, nil, err
  866. }
  867. defer cursor.Close(ctx)
  868. effects := make([]model.Effect, 0)
  869. count := 0
  870. docs := 0
  871. for cursor.Next(ctx) {
  872. if count >= offset {
  873. if docs < limit {
  874. var effect model.Effect
  875. if err = cursor.Decode(&effect); err != nil {
  876. log.Print(err)
  877. return 0, nil, err
  878. } else {
  879. effects = append(effects, effect)
  880. docs++
  881. }
  882. } else {
  883. break
  884. }
  885. }
  886. count++
  887. }
  888. return int(n), effects, nil
  889. }
  890. func (m *MongoDAO) GetEffect(effectID string) (model.Effect, error) {
  891. ctx, _ := context.WithTimeout(context.Background(), timeout)
  892. collection := m.database.Collection(effectsCollectionName)
  893. objectID, _ := primitive.ObjectIDFromHex(effectID)
  894. result := collection.FindOne(ctx, bson.M{"_id": objectID})
  895. err := result.Err()
  896. if err == mongo.ErrNoDocuments {
  897. log.Print(err)
  898. return model.Effect{}, ErrNoDocument
  899. }
  900. if err != nil {
  901. log.Print(err)
  902. return model.Effect{}, err
  903. }
  904. var effect model.Effect
  905. if err := result.Decode(&effect); err != nil {
  906. log.Print(err)
  907. return model.Effect{}, err
  908. } else {
  909. return effect, nil
  910. }
  911. }
  912. // CheckUser checking username and password... returns true if the user is active and the password for this user is correct
  913. func (m *MongoDAO) CheckUser(username string, password string) bool {
  914. username = strings.ToLower(username)
  915. pwd, ok := m.users[username]
  916. if ok {
  917. if pwd == password {
  918. return true
  919. } else {
  920. user, ok := m.GetUser(username)
  921. if ok {
  922. if user.Password == password {
  923. return true
  924. }
  925. }
  926. }
  927. }
  928. if !ok {
  929. user, ok := m.GetUser(username)
  930. if ok {
  931. if user.Password == password {
  932. return true
  933. }
  934. }
  935. }
  936. return false
  937. }
  938. // GetUser getting the usermolde
  939. func (m *MongoDAO) GetUser(username string) (model.User, bool) {
  940. username = strings.ToLower(username)
  941. ctx, _ := context.WithTimeout(context.Background(), timeout)
  942. usersCollection := m.database.Collection(usersCollectionName)
  943. var user model.User
  944. filter := bson.M{"name": username}
  945. err := usersCollection.FindOne(ctx, filter).Decode(&user)
  946. if err != nil {
  947. fmt.Printf("error: %s\n", err.Error())
  948. return model.User{}, false
  949. }
  950. password := user.Password
  951. hash := BuildPasswordHash(password)
  952. m.users[username] = hash
  953. return user, true
  954. }
  955. // DropAll dropping all data from the database
  956. func (m *MongoDAO) DropAll() {
  957. ctx, _ := context.WithTimeout(context.Background(), timeout)
  958. collectionNames, err := m.database.ListCollectionNames(ctx, bson.D{}, &options.ListCollectionsOptions{})
  959. if err != nil {
  960. log.Fatal(err)
  961. }
  962. for _, name := range collectionNames {
  963. if name != usersCollectionName {
  964. collection := m.database.Collection(name)
  965. err = collection.Drop(ctx)
  966. if err != nil {
  967. log.Fatal(err)
  968. }
  969. }
  970. }
  971. }
  972. // Stop stopping the mongodao
  973. func (m *MongoDAO) Stop() {
  974. m.ticker.Stop()
  975. m.done <- true
  976. }
  977. // AddUser adding a new user to the system
  978. func (m *MongoDAO) AddUser(user model.User) error {
  979. if user.Name == "" {
  980. return errors.New("username should not be empty")
  981. }
  982. user.Name = strings.ToLower(user.Name)
  983. _, ok := m.users[user.Name]
  984. if ok {
  985. return errors.New("username already exists")
  986. }
  987. user.Password = BuildPasswordHash(user.Password)
  988. ctx, _ := context.WithTimeout(context.Background(), timeout)
  989. collection := m.database.Collection(usersCollectionName)
  990. _, err := collection.InsertOne(ctx, user)
  991. if err != nil {
  992. fmt.Printf("error: %s\n", err.Error())
  993. return err
  994. }
  995. m.users[user.Name] = user.Password
  996. return nil
  997. }
  998. // DeleteUser deletes one user from the system
  999. func (m *MongoDAO) DeleteUser(username string) error {
  1000. if username == "" {
  1001. return errors.New("username should not be empty")
  1002. }
  1003. username = strings.ToLower(username)
  1004. _, ok := m.users[username]
  1005. if !ok {
  1006. return errors.New("username not exists")
  1007. }
  1008. ctx, _ := context.WithTimeout(context.Background(), timeout)
  1009. collection := m.database.Collection(usersCollectionName)
  1010. filter := bson.M{"name": username}
  1011. _, err := collection.DeleteOne(ctx, filter)
  1012. if err != nil {
  1013. fmt.Printf("error: %s\n", err.Error())
  1014. return err
  1015. }
  1016. delete(m.users, username)
  1017. return nil
  1018. }
  1019. // ChangePWD changes the apssword of a single user
  1020. func (m *MongoDAO) ChangePWD(username string, newpassword string, oldpassword string) error {
  1021. if username == "" {
  1022. return errors.New("username should not be empty")
  1023. }
  1024. username = strings.ToLower(username)
  1025. pwd, ok := m.users[username]
  1026. if !ok {
  1027. return errors.New("username not registered")
  1028. }
  1029. newpassword = BuildPasswordHash(newpassword)
  1030. oldpassword = BuildPasswordHash(oldpassword)
  1031. if pwd != oldpassword {
  1032. return errors.New("actual password incorrect")
  1033. }
  1034. ctx, _ := context.WithTimeout(context.Background(), timeout)
  1035. collection := m.database.Collection(usersCollectionName)
  1036. filter := bson.M{"name": username}
  1037. update := bson.D{{"$set", bson.D{{"password", newpassword}}}}
  1038. result := collection.FindOneAndUpdate(ctx, filter, update)
  1039. if result.Err() != nil {
  1040. fmt.Printf("error: %s\n", result.Err().Error())
  1041. return result.Err()
  1042. }
  1043. m.users[username] = newpassword
  1044. return nil
  1045. }
  1046. //Backup pinging the mongoDao
  1047. func (m *MongoDAO) Backup(path string) error {
  1048. // writung users
  1049. err := m.backupUsers(path)
  1050. if err != nil {
  1051. return err
  1052. }
  1053. // writing tags
  1054. err = m.backupTags(path)
  1055. if err != nil {
  1056. return err
  1057. }
  1058. // writing manufacturers
  1059. err = m.backupManufacturers(path)
  1060. if err != nil {
  1061. return err
  1062. }
  1063. // writing schematics
  1064. err = m.backupSchematics(path)
  1065. if err != nil {
  1066. return err
  1067. }
  1068. // writing effect categories
  1069. err = m.backupEffectTypes(path)
  1070. if err != nil {
  1071. return err
  1072. }
  1073. // writing effects
  1074. err = m.backupEffects(path)
  1075. if err != nil {
  1076. return err
  1077. }
  1078. return err
  1079. }
  1080. func (m *MongoDAO) backupUsers(path string) error {
  1081. path = path + "/users"
  1082. os.MkdirAll(path, os.ModePerm)
  1083. ctx, _ := context.WithTimeout(context.Background(), timeout)
  1084. collection := m.database.Collection(usersCollectionName)
  1085. cursor, err := collection.Find(ctx, bson.M{})
  1086. if err != nil {
  1087. log.Fatal(err)
  1088. }
  1089. defer cursor.Close(ctx)
  1090. count := 0
  1091. fmt.Print("backup users: ")
  1092. for cursor.Next(ctx) {
  1093. var user model.User
  1094. if err = cursor.Decode(&user); err != nil {
  1095. log.Fatal(err)
  1096. return err
  1097. } else {
  1098. user.Name = strings.ToLower(user.Name)
  1099. user.Password = BuildPasswordHash(user.Password)
  1100. data, err := json.Marshal(user)
  1101. if err != nil {
  1102. return err
  1103. }
  1104. filename := path + "/" + user.ID.Hex() + ".json"
  1105. ioutil.WriteFile(filename, data, os.ModePerm)
  1106. count++
  1107. if count%100 == 0 {
  1108. fmt.Print(".")
  1109. }
  1110. }
  1111. }
  1112. fmt.Println()
  1113. return nil
  1114. }
  1115. func (m *MongoDAO) backupTags(path string) error {
  1116. path = path + "/tags"
  1117. os.MkdirAll(path, os.ModePerm)
  1118. ctx, _ := context.WithTimeout(context.Background(), timeout)
  1119. collection := m.database.Collection(tagsCollectionName)
  1120. cursor, err := collection.Find(ctx, bson.M{})
  1121. if err != nil {
  1122. log.Fatal(err)
  1123. }
  1124. defer cursor.Close(ctx)
  1125. count := 0
  1126. fmt.Print("backup tags: ")
  1127. for cursor.Next(ctx) {
  1128. var model model.Tag
  1129. if err = cursor.Decode(&model); err != nil {
  1130. log.Fatal(err)
  1131. return err
  1132. } else {
  1133. data, err := json.Marshal(model)
  1134. if err != nil {
  1135. return err
  1136. }
  1137. filename := path + "/" + model.ID.Hex() + ".json"
  1138. ioutil.WriteFile(filename, data, os.ModePerm)
  1139. count++
  1140. if count%100 == 0 {
  1141. fmt.Print(".")
  1142. }
  1143. }
  1144. }
  1145. fmt.Println()
  1146. return nil
  1147. }
  1148. func (m *MongoDAO) backupManufacturers(path string) error {
  1149. path = path + "/manufacturers"
  1150. os.MkdirAll(path, os.ModePerm)
  1151. ctx, _ := context.WithTimeout(context.Background(), timeout)
  1152. collection := m.database.Collection(manufacturersCollectionName)
  1153. cursor, err := collection.Find(ctx, bson.M{})
  1154. if err != nil {
  1155. log.Fatal(err)
  1156. }
  1157. defer cursor.Close(ctx)
  1158. count := 0
  1159. fmt.Print("backup manufacturers: ")
  1160. for cursor.Next(ctx) {
  1161. var model model.Manufacturer
  1162. if err = cursor.Decode(&model); err != nil {
  1163. log.Fatal(err)
  1164. return err
  1165. } else {
  1166. data, err := json.Marshal(model)
  1167. if err != nil {
  1168. return err
  1169. }
  1170. filename := path + "/" + model.ID.Hex() + ".json"
  1171. ioutil.WriteFile(filename, data, os.ModePerm)
  1172. count++
  1173. if count%100 == 0 {
  1174. fmt.Print(".")
  1175. }
  1176. }
  1177. }
  1178. fmt.Println()
  1179. return nil
  1180. }
  1181. func (m *MongoDAO) backupSchematics(path string) error {
  1182. path = path + "/schematics"
  1183. os.MkdirAll(path, os.ModePerm)
  1184. ctx, _ := context.WithTimeout(context.Background(), timeout)
  1185. collection := m.database.Collection(schematicsCollectionName)
  1186. cursor, err := collection.Find(ctx, bson.M{})
  1187. if err != nil {
  1188. log.Fatal(err)
  1189. }
  1190. defer cursor.Close(ctx)
  1191. count := 0
  1192. fmt.Print("backup schematics: ")
  1193. for cursor.Next(ctx) {
  1194. var model model.Schematic
  1195. if err = cursor.Decode(&model); err != nil {
  1196. log.Fatal(err)
  1197. return err
  1198. } else {
  1199. folder := path + "/" + model.ID.Hex()
  1200. os.MkdirAll(folder, os.ModePerm)
  1201. for _, fileid := range model.Files {
  1202. if fileid != "" {
  1203. filename, err := m.GetFilename(fileid)
  1204. if err != nil {
  1205. return err
  1206. }
  1207. imagename := folder + "/" + filename
  1208. file, err := os.Create(imagename)
  1209. if err != nil {
  1210. return err
  1211. }
  1212. defer file.Close()
  1213. err = m.GetFile(fileid, file)
  1214. if err != nil {
  1215. return err
  1216. }
  1217. }
  1218. }
  1219. data, err := json.Marshal(model)
  1220. if err != nil {
  1221. return err
  1222. }
  1223. filename := folder + "/schematic.json"
  1224. ioutil.WriteFile(filename, data, os.ModePerm)
  1225. count++
  1226. if count%100 == 0 {
  1227. fmt.Print(".")
  1228. }
  1229. }
  1230. }
  1231. fmt.Println()
  1232. return nil
  1233. }
  1234. func (m *MongoDAO) backupEffectTypes(path string) error {
  1235. path = path + "/effecttypes"
  1236. os.MkdirAll(path, os.ModePerm)
  1237. ctx, _ := context.WithTimeout(context.Background(), timeout)
  1238. collection := m.database.Collection(effectTypesCollectionName)
  1239. cursor, err := collection.Find(ctx, bson.M{})
  1240. if err != nil {
  1241. log.Fatal(err)
  1242. }
  1243. defer cursor.Close(ctx)
  1244. count := 0
  1245. fmt.Print("backup effecttypes: ")
  1246. for cursor.Next(ctx) {
  1247. var model model.EffectType
  1248. if err = cursor.Decode(&model); err != nil {
  1249. log.Fatal(err)
  1250. return err
  1251. } else {
  1252. folder := path + "/" + model.ID.Hex()
  1253. os.MkdirAll(folder, os.ModePerm)
  1254. fileid := model.TypeImage
  1255. if fileid != "" {
  1256. filename, err := m.GetFilename(fileid)
  1257. if err != nil {
  1258. return err
  1259. }
  1260. imagename := folder + "/" + filename
  1261. file, err := os.Create(imagename)
  1262. if err != nil {
  1263. return err
  1264. }
  1265. defer file.Close()
  1266. err = m.GetFile(fileid, file)
  1267. if err != nil {
  1268. return err
  1269. }
  1270. model.TypeImage = filename
  1271. }
  1272. data, err := json.Marshal(model)
  1273. if err != nil {
  1274. return err
  1275. }
  1276. filename := folder + "/effecttype.json"
  1277. ioutil.WriteFile(filename, data, os.ModePerm)
  1278. count++
  1279. if count%100 == 0 {
  1280. fmt.Print(".")
  1281. }
  1282. }
  1283. }
  1284. fmt.Println()
  1285. return nil
  1286. }
  1287. func (m *MongoDAO) backupEffects(path string) error {
  1288. path = path + "/effects"
  1289. os.MkdirAll(path, os.ModePerm)
  1290. ctx, _ := context.WithTimeout(context.Background(), timeout)
  1291. collection := m.database.Collection(effectsCollectionName)
  1292. cursor, err := collection.Find(ctx, bson.M{})
  1293. if err != nil {
  1294. log.Fatal(err)
  1295. }
  1296. defer cursor.Close(ctx)
  1297. count := 0
  1298. fmt.Print("backup effects: ")
  1299. for cursor.Next(ctx) {
  1300. var model model.Effect
  1301. if err = cursor.Decode(&model); err != nil {
  1302. log.Fatal(err)
  1303. return err
  1304. } else {
  1305. folder := path + "/" + model.ID.Hex()
  1306. os.MkdirAll(folder, os.ModePerm)
  1307. fileid := model.Image
  1308. if fileid != "" {
  1309. filename, err := m.GetFilename(fileid)
  1310. if err != nil {
  1311. return err
  1312. }
  1313. imagename := folder + "/" + filename
  1314. file, err := os.Create(imagename)
  1315. if err != nil {
  1316. return err
  1317. }
  1318. defer file.Close()
  1319. err = m.GetFile(fileid, file)
  1320. if err != nil {
  1321. return err
  1322. }
  1323. model.Image = filename
  1324. }
  1325. data, err := json.Marshal(model)
  1326. if err != nil {
  1327. return err
  1328. }
  1329. filename := folder + "/effect.json"
  1330. ioutil.WriteFile(filename, data, os.ModePerm)
  1331. count++
  1332. if count%100 == 0 {
  1333. fmt.Print(".")
  1334. }
  1335. }
  1336. }
  1337. fmt.Println()
  1338. return nil
  1339. }
  1340. // Ping pinging the mongoDao
  1341. func (m *MongoDAO) Ping() error {
  1342. if !m.initialised {
  1343. return errors.New("mongo client not initialised")
  1344. }
  1345. ctx, _ := context.WithTimeout(context.Background(), timeout)
  1346. return m.database.Client().Ping(ctx, nil)
  1347. }