Skip to content

Commit

Permalink
Add: Refresh Token, Reset password, Async Emailing (#40)
Browse files Browse the repository at this point in the history
* Refactor Access Token

* Add Refresh Token

* Add reset password api (#5)

* Make Email Async (#7)

* Add: Return Name with history (#9)

* Rename Files

* rename again
  • Loading branch information
1-Harshit authored Dec 5, 2021
1 parent 150fbe5 commit 9da9d5d
Show file tree
Hide file tree
Showing 23 changed files with 606 additions and 191 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
*.db
*.exe
*.log
*.log
iitk-coin
34 changes: 34 additions & 0 deletions account/refresh_token.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package account

import (
"database/sql"

"github.com/bhuvansingla/iitk-coin/database"
)

func UpdateRefreshToken(token string, rollNo string) error {
_, err := database.DB.Exec(("UPDATE REFRESH_TOKEN SET token = $1 WHERE rollNo = $2"), token, rollNo)
return err
}

func DeleteRefreshToken(rollNo string) error {
return UpdateRefreshToken("", rollNo)
}

func InvalidateAllRefreshTokens() error {
_, err := database.DB.Exec(("UPDATE REFRESH_TOKEN SET token = $1"), "")
return err
}

func GetRefreshToken(rollNo string) (string, error) {
var token string
err := database.DB.QueryRow(("SELECT token FROM REFRESH_TOKEN WHERE rollNo = $1"), rollNo).Scan(&token)

if err == sql.ErrNoRows {
return "", nil
}
if err != nil {
return "", err
}
return token, nil
}
18 changes: 18 additions & 0 deletions account/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,35 @@ const (
func Create(rollNo string, hashedPasssword string, name string) error {

role := NormalUser

stmt, err := database.DB.Prepare("INSERT INTO ACCOUNT (rollNo, name, password, coins, role) VALUES ($1, $2, $3, $4, $5)")
if err != nil {
return errors.NewHTTPError(err, http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
}

_, err = stmt.Exec(rollNo, name, hashedPasssword, 0, role)
if err != nil {
return errors.NewHTTPError(err, http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
}

stmt, err = database.DB.Prepare("INSERT INTO REFRESH_TOKEN (rollNo, token) VALUES ($1, $2)")
if err != nil {
return errors.NewHTTPError(err, http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
}

_, err = stmt.Exec(rollNo, "")
if err != nil {
return errors.NewHTTPError(err, http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
}

return nil
}

func UpdatePassword(rollNo string, hashedPasssword string) error {
_, err := database.DB.Exec("UPDATE ACCOUNT SET password = $1 WHERE rollNo = $2", hashedPasssword, rollNo)
return err
}

func UserExists(rollNo string) (bool, error) {
row := database.DB.QueryRow("SELECT rollNo FROM ACCOUNT WHERE rollNo=$1", rollNo)
scannedRow := ""
Expand Down
103 changes: 55 additions & 48 deletions account/wallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,47 @@ package account

import (
"database/sql"

"github.com/bhuvansingla/iitk-coin/database"
)

type TransactionType string

const (
REDEEM TransactionType = "REDEEM"
REWARD TransactionType = "REWARD"
TRANSFER TransactionType = "TRANSFER"
REDEEM TransactionType = "REDEEM"
REWARD TransactionType = "REWARD"
TRANSFER TransactionType = "TRANSFER"
)

type RedeemHistory struct {
Type TransactionType `json:"type"`
Time int64 `json:"timeStamp"`
Id string `json:"txnID"`
Amount int64 `json:"amount"`
Item string `json:"item"`
Status RedeemStatus `json:"status"`
ActionByRollNo string `json:"actionByRollNo"`
Type TransactionType `json:"type"`
Time int `json:"timeStamp"`
Id string `json:"txnID"`
Amount int `json:"amount"`
Item string `json:"item"`
Status RedeemStatus `json:"status"`
ActionByRollNo string `json:"actionByRollNo"`
Name string `json:"name"`
}

type RewardHistory struct {
Type TransactionType `json:"type"`
Time int64 `json:"timeStamp"`
Id string `json:"txnID"`
Amount int64 `json:"amount"`
Remarks string `json:"remarks"`
Type TransactionType `json:"type"`
Time int `json:"timeStamp"`
Id string `json:"txnID"`
Amount int `json:"amount"`
Remarks string `json:"remarks"`
}

type TransferHistory struct {
Type TransactionType `json:"type"`
Time int64 `json:"timeStamp"`
Id string `json:"txnID"`
Amount int64 `json:"amount"`
Tax int64 `json:"tax"`
FromRollNo string `json:"fromRollNo"`
ToRollNo string `json:"toRollNo"`
Remarks string `json:"remarks"`
Type TransactionType `json:"type"`
Time int `json:"timeStamp"`
Id string `json:"txnID"`
Amount int `json:"amount"`
Tax int `json:"tax"`
FromRollNo string `json:"fromRollNo"`
ToRollNo string `json:"toRollNo"`
Remarks string `json:"remarks"`
Name string `json:"name"`
}

func GetCoinBalanceByRollNo(rollNo string) (int, error) {
Expand All @@ -54,14 +56,13 @@ func GetCoinBalanceByRollNo(rollNo string) (int, error) {

func GetWalletHistoryByRollNo(rollNo string) ([]interface{}, error) {
queryString := `
SELECT history.*
SELECT history.*, a.name
FROM (
SELECT id,
time,
$2 AS type,
fromRollNo,
toRollNo,
NULL AS rollNo,
coins,
tax,
NULL AS item,
Expand All @@ -76,7 +77,6 @@ func GetWalletHistoryByRollNo(rollNo string) ([]interface{}, error) {
$3 AS type,
NULL AS fromRollNo,
NULL AS toRollNo,
rollNo,
coins,
NULL AS tax,
item,
Expand All @@ -91,7 +91,6 @@ func GetWalletHistoryByRollNo(rollNo string) ([]interface{}, error) {
$4 AS type,
NULL AS fromRollNo,
NULL AS toRollNo,
rollNo,
coins,
NULL AS tax,
NULL AS item,
Expand All @@ -101,6 +100,12 @@ func GetWalletHistoryByRollNo(rollNo string) ([]interface{}, error) {
FROM REWARD_HISTORY
WHERE rollNo = $1
) history
LEFT JOIN ACCOUNT a
ON (
history.type = $2 AND a.rollNo = CASE WHEN history.fromRollNo = $1 THEN history.toRollNo ELSE history.fromRollNo END
OR
history.type = $3 AND a.rollNo = history.actionByRollNo
)
ORDER BY history.time DESC;`

rows, err := database.DB.Query(queryString, rollNo, TRANSFER, REDEEM, REWARD)
Expand All @@ -110,58 +115,60 @@ func GetWalletHistoryByRollNo(rollNo string) ([]interface{}, error) {
}

var history []interface{}

for rows.Next() {
var (
id int
time int64
txType TransactionType
fromRollNo sql.NullString
toRollNo sql.NullString
rollNo sql.NullString
coins sql.NullInt64
tax sql.NullInt64
item sql.NullString
status sql.NullString
id int
time int
txType TransactionType
fromRollNo sql.NullString
toRollNo sql.NullString
coins sql.NullInt64
tax sql.NullInt64
item sql.NullString
status sql.NullString
actionByRollNo sql.NullString
remarks sql.NullString
remarks sql.NullString
name sql.NullString
)
if err := rows.Scan(&id, &time, &txType, &fromRollNo, &toRollNo, &rollNo, &coins, &tax, &item, &status, &actionByRollNo, &remarks); err != nil {

if err := rows.Scan(&id, &time, &txType, &fromRollNo, &toRollNo, &coins, &tax, &item, &status, &actionByRollNo, &remarks, &name); err != nil {
return nil, err
}

var historyItem interface{}

switch txType {
case REDEEM:
historyItem = RedeemHistory{
Type: txType,
Time: time,
Time: int(time),
Id: formatTxnID(id, REDEEM),
Amount: coins.Int64,
Amount: int(coins.Int64),
Item: item.String,
Status: RedeemStatus(status.String),
ActionByRollNo: actionByRollNo.String,
Name: name.String,
}
case REWARD:
historyItem = RewardHistory{
Type: txType,
Time: time,
Id: formatTxnID(id, REWARD),
Amount: coins.Int64,
Amount: int(coins.Int64),
Remarks: remarks.String,
}
case TRANSFER:
historyItem = TransferHistory{
Type: txType,
Time: time,
Id: formatTxnID(id, TRANSFER),
Amount: coins.Int64,
Tax: tax.Int64,
Amount: int(coins.Int64),
Tax: int(tax.Int64),
FromRollNo: fromRollNo.String,
ToRollNo: toRollNo.String,
Remarks: remarks.String,
Name: name.String,
}
}

Expand Down
37 changes: 37 additions & 0 deletions auth/access_token.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package auth

import (
"net/http"
"time"

"github.com/bhuvansingla/iitk-coin/errors"
"github.com/spf13/viper"
)

func GenerateAccessToken(rollNo string) (string, error) {

expirationTime := time.Now().Add(time.Duration(viper.GetInt("JWT.ACCESS_TOKEN.EXPIRATION_TIME_IN_MIN")) * time.Minute)

return generateToken(rollNo, expirationTime)
}

func IsAuthorized(endpoint func(http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) {

return func(w http.ResponseWriter, r *http.Request) {
cookie, err := r.Cookie(viper.GetString("JWT.ACCESS_TOKEN.NAME"))
if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("bad token"))
return
}

err = isTokenValid(cookie)

if err == nil {
endpoint(w, r)
return
}

errors.WriteResponse(err, w)
}
}
Loading

0 comments on commit 9da9d5d

Please sign in to comment.