Skip to content

Commit

Permalink
Add cards and user commands (#15)
Browse files Browse the repository at this point in the history
  • Loading branch information
anothertobi authored Jun 24, 2023
1 parent 4a018fe commit c013069
Show file tree
Hide file tree
Showing 10 changed files with 276 additions and 6 deletions.
2 changes: 2 additions & 0 deletions cmd/viseca-cli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ func main() {
},
Commands: []*cli.Command{
app.NewTransactionsCommand(),
app.NewCardsCommand(),
app.NewUserCommand(),
},
}

Expand Down
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs=
Expand Down
44 changes: 44 additions & 0 deletions internal/app/cards.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package app

import (
"context"
"encoding/json"
"os"
"time"

"github.com/anothertobi/viseca-exporter/pkg/viseca"
"github.com/urfave/cli/v2"
)

// NewCardsCommand creates a new cards CLI command
func NewCardsCommand() *cli.Command {
return &cli.Command{
Name: "cards",
Usage: "list all cards",
Action: func(cCtx *cli.Context) error {
return cards(cCtx)
},
}
}

func cards(cCtx *cli.Context) error {
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel()

visecaClient, err := loginCLI(ctx, cCtx)
if err != nil {
return err
}

cardListOptions := viseca.NewDefaultCardListOptions()
cards, err := visecaClient.ListCards(ctx, cardListOptions)
if err != nil {
return err
}

encoder := json.NewEncoder(os.Stdout)

encoder.Encode(cards)

return nil
}
13 changes: 13 additions & 0 deletions internal/app/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,21 @@ import (

"github.com/PuerkitoBio/goquery"
"github.com/anothertobi/viseca-exporter/pkg/viseca"
"github.com/urfave/cli/v2"
)

func loginCLI(ctx context.Context, cCtx *cli.Context) (*viseca.Client, error) {
username := cCtx.String("username")
password := cCtx.String("password")

visecaClient, err := login(ctx, username, password)
if err != nil {
return nil, err
}

return visecaClient, nil
}

func login(ctx context.Context, username string, password string) (*viseca.Client, error) {
cookieJar, err := cookiejar.New(nil)
if err != nil {
Expand Down
5 changes: 1 addition & 4 deletions internal/app/transactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,7 @@ func transactions(cCtx *cli.Context) error {
}
cardID := cCtx.Args().First()

username := cCtx.String("username")
password := cCtx.String("password")

visecaClient, err := login(ctx, username, password)
visecaClient, err := loginCLI(ctx, cCtx)
if err != nil {
return err
}
Expand Down
42 changes: 42 additions & 0 deletions internal/app/user.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package app

import (
"context"
"encoding/json"
"os"
"time"

"github.com/urfave/cli/v2"
)

// NewUserCommand creates a new user CLI command
func NewUserCommand() *cli.Command {
return &cli.Command{
Name: "user",
Usage: "get user",
Action: func(cCtx *cli.Context) error {
return user(cCtx)
},
}
}

func user(cCtx *cli.Context) error {
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel()

visecaClient, err := loginCLI(ctx, cCtx)
if err != nil {
return err
}

user, err := visecaClient.GetUser(ctx)
if err != nil {
return err
}

encoder := json.NewEncoder(os.Stdout)

encoder.Encode(user)

return nil
}
19 changes: 19 additions & 0 deletions pkg/viseca/card.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,22 @@ func (client *Client) ListAllTransactionsOpts(ctx context.Context, card string,

return transactions, nil
}

// ListCards returns all cards for the given CardListOptions.
func (client *Client) ListCards(ctx context.Context, cardListOptions CardListOptions) (*[]Card, error) {
request, err := client.NewRequest("cards", "GET", nil)
if err != nil {
return nil, err
}

addCardListOptions(request.URL, cardListOptions)

cards := &[]Card{}

_, err = client.Do(ctx, request, cards)
if err != nil {
return nil, err
}

return cards, err
}
109 changes: 109 additions & 0 deletions pkg/viseca/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,112 @@ type PFMCategory struct {
type TransactionLinks struct {
Transactiondetails string `json:"transactiondetails"`
}

type User struct {
VisecaOneID string `json:"visecaOneId"`
Email string `json:"email"`
EmailStatus string `json:"emailStatus"`
Language string `json:"language"`
FirstName string `json:"firstName"`
LastName string `json:"lastName"`
Gender string `json:"gender"`
MaskedPhoneNumber string `json:"maskedPhoneNumber"`
LastLoginDate string `json:"lastLoginDate"`
LastLogoutType string `json:"lastLogoutType"`
DefaultChannelType string `json:"defaultChannelType"`
AppDescription string `json:"appDescription"`
AppRegistrationDate string `json:"appRegistrationDate"`
}

type Card struct {
ID string `json:"cardId"`
CardSwitch CardSwitch `json:"switch"`
MaskedCardNumber string `json:"maskedCardNumber"`
CardAccountNr string `json:"cardAccountNr"`
CardHolder CardHolder `json:"cardHolder"`
CardStatus CardStatus `json:"cardStatus"`
CardName string `json:"cardName"`
CardDescription string `json:"cardDescription"`
ExpirationDate string `json:"expirationDate"`
ProductType string `json:"productType"`
ProductLine string `json:"productLine"`
CreditIndicator string `json:"creditIndicator"`
AvailableReplacementReasons []string `json:"availableReplacementReasons"`
BonusProgram []string `json:"bonusProgram"`
MainBonusProgram string `json:"mainBonusProgram"`
Currency string `json:"currency"`
CardLimit float32 `json:"cardLimit"`
ActiveCurrency string `json:"activeCurrency"`
ActiveLimit float32 `json:"activeLimit"`
IsSelfIssued bool `json:"isSelfIssued"`
CardScheme string `json:"cardScheme"`
EmbossingLine string `json:"embossingLine"`
CardType CardType `json:"cardType"`
CallCenter string `json:"callCenter"`
CardImageDetails CardImageDetails `json:"cardImageDetails"`
CardLinks CardLinks `json:"links"`
CardGrants CardGrants `json:"grants"`
}

type CardSwitch struct {
Reason string `json:"reason"`
}

type CardHolder struct {
Firstname string `json:"firstname"`
Lastname string `json:"lastname"`
BirthDate string `json:"birthDate"`
Nationality string `json:"nationality"`
IsCurrentUser bool `json:"isCurrentUser"`
}

type CardStatus struct {
Value string `json:"value"`
AdvValue string `json:"advValue"`
Description string `json:"description"`
ChangeDate string `json:"changeDate"`
}

type CardType struct {
Value string `json:"value"`
Description string `json:"description"`
}

type CardImageDetails struct {
URL string `json:"url"`
TemplateName string `json:"templateName"`
Category string `json:"category"`
Status string `json:"status"`
DenialReason string `json:"denialReason"`
ReplacementAvailability string `json:"replacementAvailability"`
UploadContext string `json:"uploadContext"`
LastStatusUpdate string `json:"lastStatusUpdate"`
}

type CardLinks struct {
CardDetails string `json:"carddetails"`
CardImage string `json:"cardimage"`
CardSwitcherLogoImage string `json:"cardswitcherlogoimage"`
CockpitLogoImage string `json:"cockpitlogoimage"`
}

type CardGrants struct {
CanSurprizeRead bool `json:"canSurprizeRead"`
CanAccountDetailsRead bool `json:"canAccountDetailsRead"`
CanStatementSettingsRead bool `json:"canStatementSettingsRead"`
CanStatementSettingsUpdate bool `json:"canStatementSettingsUpdate"`
CanStatementDetailRead bool `json:"canStatementDetailRead"`
CanTransactionNotificationRead bool `json:"canTransactionNotificationRead"`
CanTransactionNotificationUpdate bool `json:"canTransactionNotificationUpdate"`
CanMasterpassRead bool `json:"canMasterpassRead"`
CanMasterpassUpdate bool `json:"canMasterpassUpdate"`
CanCardFreeze bool `json:"canCardFreeze"`
CanCardPINRequest bool `json:"canCardPINRequest"`
CanSmsSettingsRead bool `json:"canSmsSettingsRead"`
CanSmsSettingsUpdate bool `json:"canSmsSettingsUpdate"`
CanReplaceCard bool `json:"canReplaceCard"`
CanCardControlsRead bool `json:"canCardControlsRead"`
CanCardControlsUpdate bool `json:"canCardControlsUpdate"`
CanCouponsRead bool `json:"canCouponsRead"`
CanPanCvvPinRead bool `json:"canPanCvvPinRead"`
}
22 changes: 22 additions & 0 deletions pkg/viseca/user.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package viseca

import (
"context"
)

// GetUser returns the user information.
func (client *Client) GetUser(ctx context.Context) (*User, error) {
request, err := client.NewRequest("user", "GET", nil)
if err != nil {
return nil, err
}

user := &User{}

_, err = client.Do(ctx, request, user)
if err != nil {
return nil, err
}

return user, err
}
24 changes: 24 additions & 0 deletions pkg/viseca/viseca.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ type ListOptions struct {
DateFrom time.Time
}

// NewDefaultListOptions creates new default ListOptions.
func NewDefaultListOptions() ListOptions {
listOptions := ListOptions{}
listOptions.Offset = 0
Expand All @@ -69,6 +70,29 @@ func addListOptions(url *url.URL, listOptions ListOptions) {
url.RawQuery = query.Encode()
}

// CardListOptions known CreditIndicators are "credit" and "debit".
type CardListOptions struct {
CreditIndicators []string
}

// NewDefaultCardListOptions creates new default CardListOptions.
func NewDefaultCardListOptions() CardListOptions {
cardListOptions := CardListOptions{}
cardListOptions.CreditIndicators = []string{"credit", "debit"}

return cardListOptions
}

func addCardListOptions(url *url.URL, cardListOptions CardListOptions) {
query := url.Query()

for _, creditIndicator := range cardListOptions.CreditIndicators {
query.Add("creditIndicators", creditIndicator)
}

url.RawQuery = query.Encode()
}

// Do returns the HTTP response and decodes the JSON response body into responseBody.
func (client *Client) Do(ctx context.Context, request *http.Request, responseBody interface{}) (*http.Response, error) {
request = request.WithContext(ctx)
Expand Down

0 comments on commit c013069

Please sign in to comment.