so to offer higher context to my downside, my crudapi is about simulating a bikeshop.
I create an account by passing an account obj. to POST “localhost:8080/customers”, which if profitable provides the information to the usernames, usercontacts and passwords desk respectively. usernames maintain the person’s username, usercontacts shops their delicate knowledge(addres, fname, lname) and passwords saved their passwords as an encrypted hash. When an account is created the response {user_id: #, msg: registered }
is shipped again.
My present login route is a Publish ‘localhost:8080/person/login’.
It hashes person offered pswd and checks its in opposition to
the at the moment hashed pswd saved within the database.
Nonetheless, I need to return a token after authenticating.
Let me know if there’s something lacking.
JSON OBJECTS
Account
{
"username": string,
"fname": string,
"lname": string,
"tackle": string,
"password": string
}
usernames
{
"id": int,
"user_id": int,
"username": string,
}
usercontacts
{
"id": int,
"user_id": int,
"fname": string,
"lname": string,
"tackle": string
}
passwords
{
"id": int,
"user_id": int,
"password": string,
}
Login-Creds
{
"username": string,
"pswd": []byte
}
ROUTES
My Implmenetation
- Routes > predominant.go
- Account information & Authentication > accts.go
- Subject Error dealing with > fields.go
MAIN FILE
Create Account Route
func createAcct(r *gin.Engine) *gin.Engine {
r.POST("/customers/", func(c *gin.Context) {
var acct accts.Account
var acctErr fields.GrammarError
var acctStatus *accts.Registered
err := c.ShouldBind(&acct)
if err != nil {
acctErr.AddMsg(fields.BadRequest,
"Binding Error: didn't bind fields to account object, mismatched data-types")
c.JSON(fields.ErrorCode, acctErr)
return
}
// validate account information
acctStatus, acctErr = accts.AddAccount(&acct)
// ship response again
errMsgSize := len(acctErr.ErrMsgs)
swap {
case errMsgSize > 0:
c.JSON(fields.ErrorCode, acctErr)
default:
c.JSON(statusOK, *acctStatus)
}
//log.Println("Account: ", acct)
})
return r
}
Login Route
func logIn(r *gin.Engine) *gin.Engine {
r.POST("/person/login", func(c *gin.Context) {
var loginErr fields.GrammarError
var rqstData respBodyData
var userCred accts.LoginCred
loginErr = rqstData.FieldErr
err := c.ShouldBind(&userCred)
if err != nil {
loginErr.AddMsg(fields.BadRequest,
"Binding Error: didn't bind fields to account object, mismatched data-types")
c.JSON(fields.ErrorCode, loginErr)
return
}
// validate account information
authStatus, loginErr := accts.LogIntoAcct(userCred)
if err != nil {
loginErr.AddMsg(fields.BadRequest,
"Binding Error: didn't bind fields to account object, mismatched data-types")
c.JSON(fields.ErrorCode, loginErr)
return
}
// ship response again
errMsgSize := len(loginErr.ErrMsgs)
swap {
case errMsgSize > 0:
c.JSON(fields.ErrorCode, loginErr)
default:
c.JSON(statusOK, authStatus)
}
})
return r
}
ACCTS FILE
Add Account
// provides the account information to the appropiate tables w/ the database
func AddAccount(acct *Account) (*Registered, fields.GrammarError) {
acctErr := &fields.GrammarError{}
validateAccount(acct, acctErr)
if acctErr.ErrMsgs != nil {
return nil, *acctErr
}
// if no errors add information to appropiate tables
addUsername(acct, acctErr)
if acctErr.ErrMsgs != nil {
return nil, *acctErr
}
addUserContact(acct, acctErr)
if acctErr.ErrMsgs != nil {
return nil, *acctErr
}
// add passwords to desk, do not if err existf
addPassword(acct, acctErr)
if acctErr.ErrMsgs != nil {
// fmt.Printf("Errors in AddAccount Func, %vn", acctErr.ErrMsgs)
return nil, *acctErr
}
return &Registered{acct.ID, "registered"}, *acctErr
}
Login
// matches the consumer's username and pswd in opposition to the database
// if there is a match the person is logged in, in any other case
// there's a problem with username or password
func LogIntoAcct(userCred LoginCred) (*LoginStatus, fields.GrammarError) {
// get the person struct verify if it exists
usrs, fieldErr := readUserByUsername(userCred.UserName)
if fieldErr.ErrMsgs != nil {
return nil, fieldErr
}
// get the saved pswd hash
usr := usrs[0]
pswds, fieldErr := ReadHashByID(usr.ID)
if fieldErr.ErrMsgs != nil {
return nil, fieldErr
}
// hash the given pswd and evaluate it to whats
// saved within the databse
hashedPswd := pswds[0].Password
err := bcrypt.CompareHashAndPassword(hashedPswd, []byte(userCred.Password))
if err != nil {
// log.Printf("The Password Hash Comparability Failed: %vn", err.Error())
fieldErr.AddMsg(BadRequest, "Error: password is wrong")
return nil, fieldErr
}
return &LoginStatus{usr.ID, "LoggedIn"}, fieldErr
}