Skip to content

Commit

Permalink
user settings
Browse files Browse the repository at this point in the history
  • Loading branch information
darcys22 committed Nov 7, 2021
1 parent 7dc8f47 commit ec2ebf3
Show file tree
Hide file tree
Showing 5 changed files with 197 additions and 51 deletions.
1 change: 1 addition & 0 deletions backend/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ func register(r *gin.Engine) {
r.GET("/api/user/settings", AuthorizeJWT(), GetUserSettings)
r.POST("/api/user/changepassword", AuthorizeJWT(), ChangePassword)
r.POST("/api/user/defaultcurrency", AuthorizeJWT(), DefaultCurrency)
r.POST("/api/user/defaultlocale", AuthorizeJWT(), DefaultLocale)

// Admin Page
r.GET("/admin", AuthorizeJWT(), Admin)
Expand Down
113 changes: 79 additions & 34 deletions backend/api/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,16 @@ import (

"github.com/darcys22/godbledger-web/backend/auth"
m "github.com/darcys22/godbledger-web/backend/models"
"github.com/darcys22/godbledger-web/backend/models/sqlite"

"github.com/gin-gonic/gin"
"github.com/dgrijalva/jwt-go"

)

type UserSettings struct {
// Simply the username/email will be displayed in client
Name string `json:"name"`
// Admin or Regular user, will allow for hiding admin screens but server side will also check
Role string `json:"role"`
// Used for date parsing - https://sugarjs.com/docs/#/DateLocales
DateLocale string `json:"datelocale"`
// USD - will be used by client for all currency items
DefaultCurrency string `json:"defaultcurrency"`
}
var (
users sqlite.UserModel = sqlite.New("sqlite.db")
)

func respondWithError(ctx *gin.Context, message interface{}) {
log.Debugf("Error processing JWT: %v", message)
Expand Down Expand Up @@ -56,54 +50,105 @@ func AuthorizeJWT() gin.HandlerFunc {
}

func GetUserSettings(ctx *gin.Context) {
settings := UserSettings{}
cookie, err := ctx.Request.Cookie("access_token")
if err != nil {
respondWithError(ctx, "Cookie required")
return
}
tokenString := cookie.Value
user, err := auth.JWTAuthService().ParseUser(tokenString)
username, err := auth.JWTAuthService().ParseUser(tokenString)
if err != nil {
respondWithError(ctx, "Invalid API token")
return
} else {
settings.Name = user
//TODO sean put actual currency here
settings.DefaultCurrency = "USD"
//TODO sean put actual currency here
settings.DateLocale = "en-AU"
//settings.DateLocale = "en-US"
//TODO sean put actual role here
settings.Role = "Admin"
}
ctx.JSON(200, settings)

current_user, err := users.Get(username)
if err != nil {
respondWithError(ctx, "Could not find user")
return
}

ctx.JSON(200, current_user.Settings())
}

func ChangePassword(c *gin.Context) {
func ChangePassword(ctx *gin.Context) {
var journal m.PostJournalCommand

if err := c.BindJSON(&journal); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
if err := ctx.BindJSON(&journal); err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

if err := journal.Save(); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
}
c.JSON(200, journal)
ctx.JSON(200, journal)
}

func DefaultCurrency(c *gin.Context) {
var journal m.PostJournalCommand
func DefaultCurrency(ctx *gin.Context) {
var currency m.PostCurrencyCommand

if err := c.BindJSON(&journal); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
if err := ctx.BindJSON(&currency); err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

if err := journal.Save(); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
cookie, err := ctx.Request.Cookie("access_token")
if err != nil {
respondWithError(ctx, "Cookie required")
return
}
tokenString := cookie.Value
username, err := auth.JWTAuthService().ParseUser(tokenString)
if err != nil {
respondWithError(ctx, "Invalid API token")
return
}

current_user, err := users.Get(username)
if err != nil {
respondWithError(ctx, "Could not find user")
return
}

current_user.Currency = currency.Currency

if err := users.Save(current_user); err != nil {
ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
}
ctx.JSON(200, currency)
}

func DefaultLocale(ctx *gin.Context) {
var locale m.PostLocaleCommand

if err := ctx.BindJSON(&locale); err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

cookie, err := ctx.Request.Cookie("access_token")
if err != nil {
respondWithError(ctx, "Cookie required")
return
}
tokenString := cookie.Value
username, err := auth.JWTAuthService().ParseUser(tokenString)
if err != nil {
respondWithError(ctx, "Invalid API token")
return
}

current_user, err := users.Get(username)
if err != nil {
respondWithError(ctx, "Could not find user")
return
}

current_user.DateLocale = locale.Locale

if err := users.Save(current_user); err != nil {
ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
}
c.JSON(200, journal)
ctx.JSON(200, locale)
}
29 changes: 28 additions & 1 deletion backend/models/sqlite/users.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"golang.org/x/crypto/bcrypt"

"github.com/sirupsen/logrus"

"github.com/darcys22/godbledger-web/backend/models"
)

var log = logrus.WithField("prefix", "SqliteUsers")
Expand All @@ -30,7 +32,10 @@ func New(path string) UserModel {
email VARCHAR(255) UNIQUE NOT NULL,
hashed_password CHAR(60) NOT NULL,
created DATETIME NOT NULL,
active BOOLEAN NOT NULL DEFAULT TRUE
active BOOLEAN NOT NULL DEFAULT TRUE,
currency VARCHAR(10) NOT NULL DEFAULT "USD",
locale VARCHAR(5) NOT NULL DEFAULT "en-AU",
role VARCHAR(10) NOT NULL DEFAULT "standard"
);
`)
if err != nil {
Expand Down Expand Up @@ -116,3 +121,25 @@ func (m *UserModel) NewUser(email, password string) (int, error) {
// Otherwise, the password is correct. Return the user ID.
return id, nil
}

// We'll use the Get method to fetch details for a specific user based on their email/name
func (m *UserModel) Get(name string) (*models.User, error) {
var user models.User
stmt := "SELECT * FROM users WHERE email = ? AND active = TRUE"
row := m.DB.QueryRow(stmt, name)
err := row.Scan(&user.ID, &user.Name, &user.Email, &user.HashedPassword, &user.Created, &user.Active, &user.Currency, &user.DateLocale, &user.Role)
if err != nil {
return nil, err
}
return &user, nil
}

func (m *UserModel) Save(user *models.User) (error) {
stmt := "UPDATE users SET currency = ?, locale = ? WHERE email = ? AND active = TRUE"
_, err := m.DB.Exec(stmt, user.Currency, user.DateLocale, user.Email)
log.Info("Users Saved: ", user)
if err != nil {
return err
}
return nil
}
26 changes: 26 additions & 0 deletions backend/models/users.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,30 @@ type User struct {
HashedPassword []byte
Created time.Time
Active bool
Currency string
DateLocale string
Role string
}

type PostCurrencyCommand struct {
Currency string `json:"currency" binding:"required"`
}

type PostLocaleCommand struct {
Locale string `json:"locale" binding:"required"`
}

type UserSettingsResponse struct {
// Simply the username/email will be displayed in client
Name string `json:"name"`
// Admin or Regular user, will allow for hiding admin screens but server side will also check
Role string `json:"role"`
// Used for date parsing - https://sugarjs.com/docs/#/DateLocales
DateLocale string `json:"datelocale"`
// USD - will be used by client for all currency items
DefaultCurrency string `json:"defaultcurrency"`
}

func (u *User) Settings() UserSettingsResponse {
return UserSettingsResponse{u.Name, u.Currency, u.DateLocale, u.Role}
}
79 changes: 63 additions & 16 deletions public/views/user.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ <h5 class="card-title">Change Password</h5>
<div class="card-body">
<h5 class="card-title">Default Currency</h5>
<div>
<form class="validate-form" id="changedefaultcurrency">
<form class="validate-form" action="/api/user/defaultcurrency" method="post" id="changedefaultcurrency">
<div class="input-group flex-nowrap m-1">
<input type="text" class="form-control" placeholder="USD" aria-label="Default Currency" aria-describedby="addon-wrapping">
<input type="text" name="currency" class="form-control" placeholder="USD" aria-label="Default Currency" aria-describedby="addon-wrapping">
</div>
<button type="submit" class="btn btn-primary m-1">Change Default Currency</button>
</form>
Expand All @@ -56,20 +56,13 @@ <h5 class="card-title">Default Currency</h5>
<div class="card m-5" style="width: 18rem;">
<div class="card-body">
<h5 class="card-title">Default Date Locale</h5>
<div>
<form class="validate-form" id="changedefaultcurrency">
<div class="dropdown show">
<a class="btn btn-secondary dropdown-toggle" href="#" role="button" id="dropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Dropdown link
</a>

<div class="dropdown-menu" aria-labelledby="dropdownMenuLink">
<a class="dropdown-item" href="#">AUS - DD/MM/YYYY</a>
<a class="dropdown-item" href="#">USA - MM/DD/YYYY</a>
</div>
</div>
<button type="submit" class="btn btn-primary m-1">Change Default Currency</button>
</form>
<div class="dropdown show">
<a class="btn btn-secondary dropdown-toggle" href="#" role="button" id="dropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Dropdown link </a>
<div class="dropdown-menu" aria-labelledby="dropdownMenuLink">
<a class="dropdown-item" href="#" data-value="en-AU">en-AU - DD/MM/YYYY</a>
<a class="dropdown-item" href="#" data-value="en-US">en-US - MM/DD/YYYY</a>
</div>
</div>
</div>
</div>
Expand Down Expand Up @@ -100,6 +93,60 @@ <h5 class="card-title">Default Date Locale</h5>
});
});

$( "#changedefaultcurrency" ).submit(function( event ) {
event.preventDefault();

var $form = $(this)
url = $form.attr('action');
console.log("sean remove this")

var currency = $('input[name = currency]').val()
console.log(currency)
if (currency.length > 0) {
fetch(url,{
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=utf-8'
},
body: JSON.stringify({
currency: currency,
})
})
.then(response => response.json())
.then(data => {
console.log(data);
})
.catch(error => console.error(error))
}
});

$(".dropdown-menu a").click(function(){
locale = $(this).data('value')
$("#dropdownMenuLink").html(locale);
fetch("api/user/defaultlocale",{
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=utf-8'
},
body: JSON.stringify({
locale: locale,
})
})
.then(response => response.json())
.then(data => {
console.log(data);
if (typeof Date.setLocale !== 'undefined') {
Date.setLocale(data.locale);
user.datelocale = data.locale
}
})
.catch(error => console.error(error))
});

setTimeout(function(){
$("#dropdownMenuLink").html(user.datelocale);
}, 1000);

</script>
<!--Embed the footer.html template at this location-->
{{ template "footer.html" .}}

0 comments on commit ec2ebf3

Please sign in to comment.