Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Product api #7

Open
wants to merge 127 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
127 commits
Select commit Hold shift + click to select a range
5e308d4
product api get
RohitNalePUCSD Sep 10, 2020
d48f292
Product Creation API, Get Product By Category API, Delete Product API…
Sep 10, 2020
412d180
product api
RohitNalePUCSD Sep 11, 2020
11b4809
product api
RohitNalePUCSD Sep 11, 2020
807246d
add serial contraint
RohitNalePUCSD Sep 11, 2020
43de867
add insert migration file
RohitNalePUCSD Sep 11, 2020
fcf79b2
add change table variable
RohitNalePUCSD Sep 11, 2020
154ed77
Product's json tag names are changed as per UI side request. Migratio…
Sep 11, 2020
84b6a9c
add assets new images
RohitNalePUCSD Sep 11, 2020
737fbc9
createProduct function update change
RohitNalePUCSD Sep 11, 2020
1d2b55d
Brand, Color, Size added in product struct. Products Table migration …
Sep 11, 2020
d81f72f
paginations
RohitNalePUCSD Sep 12, 2020
fe6530d
Merge branch 'product_api' of https://github.com/joshsoftware/go-e-co…
RohitNalePUCSD Sep 12, 2020
aa31335
add paginations
RohitNalePUCSD Sep 12, 2020
0230648
Total Pages are also sent as response.Filters of categoryId, brand, s…
Sep 12, 2020
1af2b3a
Pagination for Product filter API added. getProductsBy CategoryId API…
Sep 12, 2020
b2bc045
error handle
RohitNalePUCSD Sep 12, 2020
315d9a8
update filter file
RohitNalePUCSD Sep 14, 2020
7348dd8
SQL Injection Attack are handled for product filters, using Regular E…
Sep 14, 2020
57ef73e
setup test case file
RohitNalePUCSD Sep 14, 2020
5a9e6c7
Merge branch 'product_api' of https://github.com/joshsoftware/go-e-co…
RohitNalePUCSD Sep 14, 2020
cfd9b57
Tax field added in Products. Migration of products changed for it. Al…
Sep 15, 2020
c037f05
add product_http_test cases
RohitNalePUCSD Sep 15, 2020
934d310
add product_http_test cases
RohitNalePUCSD Sep 15, 2020
66dbd00
add filter_http_test cases
RohitNalePUCSD Sep 15, 2020
a440959
Search By some pattern API added. Testing of filters added.
Sep 15, 2020
94f7ae5
add search handler
RohitNalePUCSD Sep 16, 2020
30d53d2
add search function handler
RohitNalePUCSD Sep 16, 2020
d592721
Search API for product has been modified, duplicate keywords handled…
Sep 16, 2020
8ca802e
Changed contents of .gitignore
Sep 16, 2020
c7b8b95
update search function
RohitNalePUCSD Sep 16, 2020
31ad133
Changes made in Search Product By text API, only fields on which user…
Sep 16, 2020
0285299
update search function
RohitNalePUCSD Sep 16, 2020
c8baf4b
Merge branch 'product_api' of https://github.com/joshsoftware/go-e-co…
RohitNalePUCSD Sep 16, 2020
397ef51
add new test case
RohitNalePUCSD Sep 16, 2020
2a8d0ba
Redundant code eliminated. Test Cases have been checked for equal exp…
Sep 17, 2020
a8e661b
Added API for Product Updation.
Sep 17, 2020
eb75d97
update create product handler
RohitNalePUCSD Sep 17, 2020
2f5faf0
change migration file
RohitNalePUCSD Sep 17, 2020
d9c220c
Removed Product Images Table. Storing ProductImages as an Array in Pr…
Sep 17, 2020
a9cdad9
change MR
RohitNalePUCSD Sep 17, 2020
5be5e77
Remove URL's scanning with for loop logic.
Sep 18, 2020
0b94cf1
migration change
RohitNalePUCSD Sep 18, 2020
406005f
Merge branch 'product_api' of https://github.com/joshsoftware/go-e-co…
RohitNalePUCSD Sep 18, 2020
46767ab
add new test case and delete product_image.go
RohitNalePUCSD Sep 18, 2020
22714ac
Removed Unnecessary Comments. Offset Calculation done in Program itse…
Sep 18, 2020
9362c17
Solved Merge Conflicts
Sep 18, 2020
bea4477
change MR
RohitNalePUCSD Sep 18, 2020
0494b8a
calculat offset and update handler function
RohitNalePUCSD Sep 18, 2020
99f3d8b
remove retrun by name in function
RohitNalePUCSD Sep 18, 2020
55fae1d
Reduced DB Calls in CreateProduct, updateStock, updateProduct. Rename…
Sep 18, 2020
7e50ce1
Defaults in Products migrations is changed. ListProducts now take lim…
Sep 18, 2020
e0cee44
update changes as per requird
RohitNalePUCSD Sep 18, 2020
dcb64e2
Added comments so that code will not panic when db isn't present.This…
Sep 20, 2020
41d5e84
Category table's id renamed to cid, name renamed to cname. Product ta…
Sep 20, 2020
90bab4e
HTTP Test cases are all made running.
Sep 20, 2020
31450ba
add new changes
RohitNalePUCSD Sep 21, 2020
c7c240d
add update code
RohitNalePUCSD Sep 24, 2020
be181f9
User can also add image when creating Product. gorilla's schema libra…
Sep 24, 2020
f8e7738
add update code
RohitNalePUCSD Sep 25, 2020
1c63b46
update api chnages add images in form value
RohitNalePUCSD Sep 25, 2020
13436c2
Added count- 1 > offset logic to avoid getting out of range pages as …
Sep 25, 2020
91d9238
Product Count Query Start made as one.
Sep 25, 2020
617261a
add delete images in update products
RohitNalePUCSD Sep 25, 2020
b9015e8
Merge branch 'product_api' of https://github.com/joshsoftware/go-e-co…
RohitNalePUCSD Sep 25, 2020
69c1fd9
add delete images function in update products api
RohitNalePUCSD Sep 25, 2020
4dd7881
Images moved to assets/productImages folder. Transactions removed in …
Sep 25, 2020
8ecb672
Images were renamed for proper insertions. Image insertion and updati…
Sep 25, 2020
7152444
Unnecessary images removed. product.
Sep 25, 2020
318e076
Just a change in migrations.sql
Sep 25, 2020
58bb9e5
We are also deleting images of Products whenever product is deleted.
Sep 25, 2020
b27f0ff
add delete images function and display create product data
RohitNalePUCSD Sep 26, 2020
5485466
Color and Size are just string than pointer to string. Their default …
Sep 26, 2020
d9227f5
add createproduct api in multiformvalue run test case
RohitNalePUCSD Sep 30, 2020
130d8bd
CreateProduct Test modified to work with mock request than real request.
Sep 30, 2020
d14af6a
add createproduct api
RohitNalePUCSD Sep 30, 2020
654684b
Update Product Failure Test Cases added along with Validation Failure…
Sep 30, 2020
d39968f
update product_test createProduct using mockdb
RohitNalePUCSD Sep 30, 2020
81dbe41
update product_test updateProductSuccess add test case
RohitNalePUCSD Sep 30, 2020
a4050b9
update product_http listProduct handler remove scan total count
RohitNalePUCSD Oct 1, 2020
ad96960
NaN's are handeled in all floating variable fields by Validate Method.
Oct 1, 2020
eacf607
check api
RohitNalePUCSD Oct 1, 2020
f808e22
Merge branch 'product_api' of https://github.com/joshsoftware/go-e-co…
RohitNalePUCSD Oct 1, 2020
8b5b630
remove print methods
RohitNalePUCSD Oct 1, 2020
8ecb804
Added Logic for Fetching Category Name in insert Query itself.
Oct 1, 2020
5860ba0
Merge branch 'product_api' of https://github.com/joshsoftware/go-e-co…
RohitNalePUCSD Oct 1, 2020
494a5cd
updateProductQuery changed from normal Exec to NamedQuery. Also Categ…
Oct 2, 2020
0ef02e9
Merge branch 'product_api' of https://github.com/joshsoftware/go-e-co…
RohitNalePUCSD Oct 5, 2020
06a84d4
add CHECK constraint and change test cases
RohitNalePUCSD Oct 5, 2020
849692f
Fine Grained the CHECK constraints. Deleted Wrangler and Poloshirt im…
Oct 6, 2020
d99da87
add Full URL of images and add statusConflict already exists product
RohitNalePUCSD Oct 6, 2020
3c9dff1
change migration
RohitNalePUCSD Oct 6, 2020
a7f4bee
Migration.sql's names chnaged along with solving merge conflicts.
Oct 6, 2020
13943e2
StatusConflict Code Added as per UI Side's Request.
Oct 6, 2020
2256b47
change migration
RohitNalePUCSD Oct 6, 2020
4ed8442
Merge branch 'product_api' of https://github.com/joshsoftware/go-e-co…
RohitNalePUCSD Oct 6, 2020
12faee9
Message Responses are made clear and to point.
Oct 6, 2020
62a4aa1
change migration
RohitNalePUCSD Oct 6, 2020
4557500
Merge branch 'product_api' of https://github.com/joshsoftware/go-e-co…
RohitNalePUCSD Oct 6, 2020
c4f7a8d
Test Cases for Update API are Updated.
Oct 6, 2020
97337be
remove switch case use default case
RohitNalePUCSD Oct 6, 2020
a18cbb7
Merge branch 'product_api' of github.com:joshsoftware/go-e-commerce i…
Oct 6, 2020
365a7ac
remove switch case use default case
RohitNalePUCSD Oct 6, 2020
aa31dd8
Blanks are handled for image url creation. If image isn't sent with f…
Oct 6, 2020
e667782
remove extra database call in UpdateProductStockById
RohitNalePUCSD Oct 7, 2020
6e975a4
Response messages are made more specific. In UpdateProductById Method…
Oct 7, 2020
eb7518c
remove redundant code in response msg
RohitNalePUCSD Oct 8, 2020
ad25b13
remove redundant code in response msg
RohitNalePUCSD Oct 9, 2020
72f8370
List Products DB calls reduced. TotalRecords variable added to Produc…
Oct 9, 2020
6ba69a2
Merge branch 'product_api' of https://github.com/joshsoftware/go-e-co…
RohitNalePUCSD Oct 9, 2020
ec8f629
Added new structure by name Records for holding totalRecords. Deleted…
Oct 9, 2020
357d499
Merge branch 'product_api' of https://github.com/joshsoftware/go-e-co…
RohitNalePUCSD Oct 9, 2020
0348281
Filter Product API is now only 1 database call!
Oct 9, 2020
fcd75ee
Merge branch 'product_api' of https://github.com/joshsoftware/go-e-co…
RohitNalePUCSD Oct 9, 2020
bc4427b
optimize database call in SearchProducts API
RohitNalePUCSD Oct 9, 2020
2e83ce2
Variable name change from isFiltered to searchQuery in Search Impleme…
Oct 9, 2020
e546f6c
Delete Product has QueryRowx instead of Queryx, this makes Scan possi…
Oct 9, 2020
e987b80
README.md Updated with Proper instructions.
Oct 9, 2020
ff5827c
Documentation added in docs folder.
Oct 9, 2020
1cca0b1
Test Cases updated to Run properly.
Oct 9, 2020
bbf93a4
Records type added. Products() Method is added to Records. This Metho…
Oct 9, 2020
9ff7ad3
Added TODOs which are capabilities and security issues.These are supp…
Oct 14, 2020
6e5683e
add new statusConflict in createProduct is product already exsits
RohitNalePUCSD Oct 16, 2020
eae3c48
add new validation conditions
RohitNalePUCSD Oct 16, 2020
1a33c88
Stored XSS attack is handeled in updateProduct and createProduct Hand…
Oct 16, 2020
47d9422
update test case conditions in product api
RohitNalePUCSD Oct 16, 2020
ade9366
Dockerfile added. README has instructions for image pulling directly …
Oct 31, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
FROM golang:1.14.10 AS builder
RUN mkdir /app
ADD . /app
WORKDIR /app
RUN CGO_ENABLED=0 GOOS=linux go build -o go-e-commerce_product-api

FROM alpine:latest AS production
COPY --from=builder /app .
ENTRYPOINT ["./go-e-commerce_product-api"]
CMD ["start"]
91 changes: 76 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,32 +1,93 @@
## Golang Boilerplate
Golang boilerplate to kickstart any go api project. This supports 2 database configurations currently:
Assumption 1: You are simran.
Assumption 2: Words in CAPITAL_CASE are meant to be set by simran.
Assumption 3: Port 33001 must be free, else specify other port in application.yml .
Assumption 4: Postgresql server is running on port 5432, if on other port then makes appropriate changes in application.yml.
Assumption 5: All the source code is pulled from git and you are currently on product_api branch

* MongoDB
* Postgres (default)
## Setting Up Database
Use PostgresQL database with version greater than 12.

### Installing and configuring the boilerplate!

Get the install.sh script into your microservice development directory.
Create a database in PostgresQL via commandline
sudo -u postgres createdb --owner=USERNAME DATABASE_NAME
example:
```
sudo -u postgres createdb --owner=simran Commerce
```

```
[Just For Knowledge]
Drop a database in PostgresQL via commandline
dropdb -h localhost -p PORT_NUMBER -U USERNAME DATABASE_NAME
example:
dropdb -h localhost -p 5432 -U simran Commerce
```

Copy your DB_URI to application.yml file
DB_URI: "postgresql://USERNAME:PASSWORD@localhost:PORT_NUMBER/DATABASE_NAME?sslmode=disable"
example:
```
"postgresql://simran:root@localhost:5432/Commerce?sslmode=disable"
```
### golang version
golang version 1.14.10

### Build the Product_api
```
wget https://raw.githubusercontent.com/joshsoftware/golang-boilerplate/master/install.sh
go build
```

Run the script with the options:
You should see some executable getting created with name go-e-commerce

### Migrate
```
. ./install.sh -p package_name [-d {mongo|pg}] [-h]
./go-e-commerce migrate
```

-p: [mandatory] Usually your github handle and service name. Eg. gautamrege/testly or github.com/corp/pkg/service
This will create tables in the DATABASE_NAME you specified in application.yml

-d: [optional] Default: pg. Specify 'mongo' for mongoDB setup
### Copying Dump to Database
Copy the migration.sql dump to this db with following command.
psql DATABASE_NAME < PATH_TO_migration.sql
example :
```
psql Commerce < /home/simran/Desktop/Josh/InternProject/go-e-commerce/migration.sql
```

-h: [optional] Display help
You should see that all records have been inserted successfully, if not either you messed up or there is version problem or our code is broke.

### Testing

Run test locally
### Run directly on host
```
$ make test
./go-e-commerce start
```

### Run on Docker

Dependency 1: You must have docker installed with sudo rights.
Dependency 2: You must have all migrations already created(See Migrate).

## First Way
Build Locally and run
```
docker build -t joshsoftware/go-e-commerce_product-api:v1 .


docker run -it -p 33001:33001 \
--network=host \
joshsoftware/go-e-commerce_product-api:v1
```

## Second Way
Directly Pull the docker image from https://hub.docker.com/repository/docker/skavhar1998/go-e-commerce_product-api and then run.

```
docker pull skavhar1998/go-e-commerce_product-api:v1

docker run -it -p 33001:33001 \
--network=host \
skavhar1998/go-e-commerce_product-api:v1
```

### For documentation, refer the docs folder
docs only include Product_api documentation
Binary file added assets/productImages/AndroidLEDTV1.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/productImages/AndroidLEDTV2.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/productImages/AndroidLEDTV3.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/productImages/Charger1.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/productImages/Charger2.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/productImages/Charger3.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/productImages/DragonJacket1.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/productImages/DragonJacket2.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/productImages/DragonJacket3.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/productImages/Football1.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/productImages/Football2.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/productImages/Football3.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/productImages/Football4.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/productImages/Football5.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/productImages/Football6.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/productImages/MensRunningShoes1.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/productImages/MensRunningShoes2.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/productImages/MensRunningShoes3.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/productImages/RelaxWatch1.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/productImages/RelaxWatch2.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/productImages/RelaxWatch3.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/productImages/SonataWatch1.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/productImages/SonataWatch2.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/productImages/SonataWatch3.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/productImages/SonyDSC1.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/productImages/SonyDSC2.jpeg
Binary file added assets/productImages/SonyDSC3.jpeg
Binary file added assets/productImages/Titan Watch-151948565.png
Binary file added assets/productImages/TitanWatch1.jpeg
Binary file added assets/productImages/TitanWatch2.jpeg
Binary file added assets/productImages/TitanWatch3.jpeg
Binary file added assets/productImages/WingsofFire1.jpeg
Binary file added assets/productImages/WingsofFire2.jpeg
Binary file added assets/productImages/Wrangler1.jpeg
Binary file added assets/productImages/Wrangler2.jpeg
Binary file added assets/productImages/poloshirt1.jpeg
Binary file added assets/productImages/poloshirt2.jpeg
Binary file added assets/productImages/poloshirt3.jpeg
Binary file added assets/productImages/vivkananadbook1.jpeg
Binary file added assets/productImages/vivkananadbook2.jpeg
1 change: 1 addition & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,6 @@ func checkIfSet(key string) {
if !viper.IsSet(key) {
err := errors.New(fmt.Sprintf("Key %s is not set", key))
panic(err)
//logger.WithField("err", err.Error()).Error("Error Couldn't find db!")
}
}
7 changes: 7 additions & 0 deletions db/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package db

type ErrorResponse struct {
Code string `json:"code"`
Message string `json:"message"`
Fields map[string]string `json:"fields"`
}
37 changes: 37 additions & 0 deletions db/common_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package db

import (
"testing"
"time"

"github.com/DATA-DOG/go-sqlmock"
"github.com/jmoiron/sqlx"
logger "github.com/sirupsen/logrus"
"github.com/stretchr/testify/suite"
)

var (
now time.Time
mockedRows *sqlmock.Rows
)

func InitMockDB() (s Storer, sqlConn *sqlx.DB, sqlmockInstance sqlmock.Sqlmock) {
mockDB, sqlmock, err := sqlmock.New()
if err != nil {
logger.WithField("err:", err).Error("error initializing mock db")
return
}

sqlmockInstance = sqlmock
sqlxDB := sqlx.NewDb(mockDB, "sqlmock")

var pgStoreConn pgStore
pgStoreConn.db = sqlxDB

return &pgStoreConn, sqlxDB, sqlmockInstance
}

func TestExampleTestSuite(t *testing.T) {
suite.Run(t, new(ProductsTestSuite))
suite.Run(t, new(FilterTestSuite))
}
13 changes: 9 additions & 4 deletions db/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@ package db

import (
"context"
"mime/multipart"
)

type Storer interface {
ListUsers(context.Context) ([]User, error)
//Create(context.Context, User) error
//GetUser(context.Context) (User, error)
//Delete(context.Context, string) error
ListProducts(context.Context, int, int) (int, []Product, error)
FilteredProducts(context.Context, Filter, string, string) (int, []Product, error)
SearchProductsByText(context.Context, string, string, string) (int, []Product, error)
CreateProduct(context.Context, Product, []*multipart.FileHeader) (Product, error, int)
DeleteProductById(context.Context, int) error
UpdateProductById(context.Context, Product, int, []*multipart.FileHeader) (Product, error, int)
UpdateProductStockById(context.Context, int, int) (Product, error, int)
GetProductByID(context.Context, int) (Product, error)
}
164 changes: 164 additions & 0 deletions db/filters.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
package db

import (
"context"
"fmt"
"regexp"
"strings"

logger "github.com/sirupsen/logrus"
)

var (
filterSearchProduct = `SELECT count(*) OVER() AS total,*
FROM products p
INNER JOIN category c
ON p.cid = c.cid`
)

type Filter struct {
// Below fields are what we may receive as Parameters in request body
CategoryId string
Price string
Brand string
Size string
Color string
// These Flags will help us format our query, true means that field exists in Request Parameters
CategoryFlag bool
PriceFlag bool
BrandFlag bool
SizeFlag bool
ColorFlag bool
}

// TODO Add condition and sort capabilities for both these APIs
// These capabilities are suppossed to make filter and search APIs
// really really dynamic and much robust.
// eg for condition -> WHERE cid >= 5 AND tax <= 4
// eg for sort -> category_id = desc, price asc

// @Title FilteredProducts
// @Description Get the products that are filtered as per request Parameters
// @Accept request.Context, Filter struct's object
// @Success total= (count of filtered products), error=nil
// @Failure total=0, error= "Some Error"
func (s *pgStore) FilteredProducts(ctx context.Context, filter Filter, limitStr string, offsetStr string) (int, []Product, error) {

var found bool
var records Records
var err error

// helper will be used in making query dynamic.
// See how it's getting concatanation added in case a flag was Filter Flag is true
sqlRegexp := ``
filterQuery := ` `
if filter.CategoryFlag == true {
filterQuery += ` c.cid = ` + filter.CategoryId + ` AND`
sqlRegexp += filter.CategoryId
found = true
}
if filter.BrandFlag {
filterQuery += ` LOWER(p.brand) = LOWER('` + filter.Brand + `') AND`
sqlRegexp += filter.Brand
found = true
}
if filter.SizeFlag {
filterQuery += ` LOWER(p.size) = LOWER('` + filter.Size + `') AND`
sqlRegexp += filter.Size
found = true
}
if filter.ColorFlag {
filterQuery += ` LOWER(p.color) =LOWER('` + filter.Color + `') AND`
sqlRegexp += filter.Color
found = true
}
if found {
var validParameters = regexp.MustCompile(`^[\w ]+$`)
if validParameters.MatchString(sqlRegexp) == false {
err = fmt.Errorf("Possible SQL Injection Attack.")
logger.WithField("err", err.Error()).Error("Error In Parameters, special Characters are present.")
return 0, []Product{}, err
}
filterQuery = ` WHERE ` + filterQuery[:len(filterQuery)-3]
}

filterQuery = filterSearchProduct + filterQuery

if filter.PriceFlag {
filterQuery += ` ORDER BY p.price ` + filter.Price + `, p.id LIMIT ` + limitStr + ` OFFSET ` + offsetStr + ` ;`
} else {
filterQuery += ` ORDER BY p.id LIMIT ` + limitStr + ` OFFSET ` + offsetStr + ` ;`
}

err = s.db.Select(&records, filterQuery)
if err != nil {
logger.WithField("err", err.Error()).Error("Error fetching Products from database")
return 0, []Product{}, err
} else if len(records) == 0 {
err = fmt.Errorf("Desired page not found, Offset was big")
logger.WithField("err", err.Error()).Error("Products don't exist by such filters!")
return 0, []Product{}, err
}

return records[0].TotalRecords, records.Products(), nil
}

// @Title SearchRecords
// @Description Get records that are searched as per request Parameter "text" along with count
// @Accept request.Context, text as string, limitStr, pageStr
// @Success total= (count of search qualifying records), error=nil
// @Failure total=0, error= "Some Error"
func (s *pgStore) SearchProductsByText(ctx context.Context, text string, limitStr string, offsetStr string) (int, []Product, error) {

var records Records
var validParameters = regexp.MustCompile(`^[\w ]+$`)

// if There are other chracters than word and space
if validParameters.MatchString(text) == false {
err := fmt.Errorf("Possible SQL Injection Attack.")
logger.WithField("err", err.Error()).Error("Error In Parameters, special Characters are present.")
return 0, []Product{}, err
}

// Split the text into slice of strings, max 10 first words will be considered
textSlice := strings.SplitN(text, " ", 11)

// If there are more than 10 words in search, ask user to be less verbose
if len(textSlice) > 10 {
err := fmt.Errorf("Unnecessary detailed text given.")
logger.WithField("err", err.Error()).Error("Error In Parameters, very detailed!.")
return 0, []Product{}, err
}

// Removing Duplicate words from textSlice
textMap := make(map[string]bool, 10)
for i := 0; i < len(textSlice); i++ {
textMap[textSlice[i]] = true
}

searchQuery := ` WHERE `

// iterate over all the textMap
for key := range textMap {
searchQuery += `
LOWER(p.name) LIKE LOWER('%` + key + `%') OR
LOWER(p.brand) LIKE LOWER('%` + key + `%') OR
LOWER(c.cname) LIKE LOWER('%` + key + `%') OR`
}

// remove that last OR from searchQuery
searchQuery = filterSearchProduct + searchQuery[:len(searchQuery)-2] +
` LIMIT ` + limitStr + ` OFFSET ` + offsetStr + ` ;`

err := s.db.Select(&records, searchQuery)
if err != nil {
logger.WithField("err", err.Error()).Error("Error fetching Products from database")
return 0, []Product{}, err
} else if len(records) == 0 {
err = fmt.Errorf("Either Offset was big or No Records Present in database!")
logger.WithField("err", err.Error()).Error("database Returned total record count as 0")
return 0, []Product{}, err
}

return records[0].TotalRecords, records.Products(), nil
}
Loading