How to write response with searched data - go-swagger & gorm - go

I used go-swagger and gorm for MySQL queries and one of my handlers is (retreiving one record)
api.UsersUserGetByIDHandler = users.UserGetByIDHandlerFunc(func(params users.UserGetByIDParams) middleware.Responder {
db := dbConn()
user := User{}
res := db.Table("users").Where("id = ?", params.UserID).Select("id, email, password, name").Scan(&user)
if res.RecordNotFound() {
message := "User not exists"
return users.NewUserGetByIDDefault(500).WithPayload(&models.Error{Message: &message})
}
log.Info(user) // {21 bxffcgb#emagggil.com 123456 Second}
return users.NewUserGetByIDOK() //How return right response there???
//.WriteResponse()
})
or retreive all data from table users
api.UsersUserListHandler = users.UserListHandlerFunc(func(params users.UserListParams) middleware.Responder {
db := dbConn()
var user []User
var count int
db.Table("users").Select("id, email, password, name").Scan(&user).Count(&count)
log.Info(db.RecordNotFound())
if count == 0 {
message := "User not exists"
return users.NewUserGetByIDDefault(500).WithPayload(&models.Error{Message: &message})
}
return users.NewUserGetByIDOK()
})
User Gorm struct is
type User struct { // user
ID int64 `gorm:"AUTO_INCREMENT"`
Email string `gorm:"type:varchar(200);unique_index"`
Password string `gorm:"size:200"`
Name string `gorm:"type:varchar(200)`
}
and same as models.Users
How properly return data there? I tried with WriteResponse and WithPayload but unsuccessful

There is an answer:
First change
user := User{}
to
user := new(models.Users)
and add at the end
ret := make([]*models.Users, 0)
ret = append(ret, user)
return users.NewUserGetByIDOK().WithPayload(ret)
WithPayload functions form file *_responses.go is defined as
// WithPayload adds the payload to the user get by Id o k response
func (o *UserGetByIDOK) WithPayload(payload []*models.Users) *UserGetByIDOK {
o.Payload = payload
return o
}

Related

graphql mutation query error using graph-gophers/graphql-go package

PROBLEM
the mutation below
mutation {
signUp(signUpInput: {email: "newuser#gmail.com", username: "newUser", password: "asdfasdfawerawer"}) {
email
username
}
}
errors out the following
{
"errors": [
{
"message": "Cannot query field \"email\" on type \"SignUpResponse\".",
"locations": [
{
"line": 3,
"column": 5
}
]
},
{
"message": "Cannot query field \"username\" on type \"SignUpResponse\".",
"locations": [
{
"line": 4,
"column": 5
}
]
}
]
}
EXPECTATION
{
"data": {
"signUp": {
"email": "newuser#gmail.com",
"username": "newUser"
}
}
}
snippets of code
schema.graphql snippet
...
input SignUpInput {
username: String!
email: String!
password: String!
}
type Mutation {
signUp(signUpInput: SignUpInput): SignUpResponse!
}
type SignUpResponse {
ok: Boolean!
error: String
addedUser: User
}
resolvers.go snippet
...
// UserResolver ingests properties from User
type UserResolver struct{ u *User }
// UserID returns the userId of the user
func (r *UserResolver) UserID() graphql.ID {
return r.u.UserID
}
// Username returns the username of the user
func (r *UserResolver) Username() string {
return r.u.Username
}
// Email returns the email of the user
func (r *UserResolver) Email() string {
return r.u.Email
}
// Password returns the password of the user
func (r *UserResolver) Password() string {
return r.u.Password
}
type SignUpArgs struct {
Username string
Email string
Password string
}
// SignUp returns a new User from Db and its responses
func (r *RootResolver) SignUp(args struct{ SignUpInput *SignUpArgs }) (*SignUpResolver, error) {
// Find user:
u, err := r.Db.CreateUser(args.SignUpInput)
// need to deal with this different, so sort of error if we can't create the user
// a. user already exists
// b. email already exists
if err != nil {
// error creating the user
msg := "already signed up"
return &SignUpResolver{
Status: false,
Msg: &msg,
User: nil,
}, err
}
return &SignUpResolver{
Status: true,
Msg: nil,
User: &UserResolver{&u},
}, nil
}
// SignUpResolver is the response type
type SignUpResolver struct {
Status bool
Msg *string
User *UserResolver
}
// Ok for SignUpResponse
func (r *SignUpResolver) Ok() bool {
return r.Status
}
// Error for SignUpResponse
func (r *SignUpResolver) Error() *string {
return r.Msg
}
// AddedUser for SignUpResponse
func (r *SignUpResolver) AddedUser() *UserResolver {
return r.User
}
postgres.go - db operations
// User returns a single user
func (d *Db) User(uid graphql.ID) (User, error) {
var (
sqlStatement = `SELECT * FROM users WHERE user_id=$1;`
row *sql.Row
err error
u User
)
row = d.QueryRow(sqlStatement, uid)
err = row.Scan(
&u.UserID,
&u.Username,
&u.Email,
&u.Password,
)
util.Check(err, "row.Scan")
return u, nil
}
// CreateUser - inserts a new user
func (d *Db) CreateUser(i *SignUpArgs) (User, error) {
var (
sqlStatement = `
INSERT INTO users (email, username, password)
VALUES ($1, $2, $3)
RETURNING user_id`
userID graphql.ID
row *sql.Row
err error
u User
)
/***************************************************************************
* retrieve the UserID of the newly inserted record
* db.Exec() requires the Result interface with the
LastInsertId() method which relies on a returned value from postgresQL
* lib/pq does not however return the last inserted record
****************************************************************************/
row = d.QueryRow(sqlStatement, i.Email, i.Username, i.Password)
if err = row.Scan(&userID); err != nil {
// err: username or email is not unqiue --> user already exsits
return u, err
}
u, _ = d.User(userID)
return u, nil
}
I've tried to change the CreateUser to this
// CreateUser - inserts a new user
func (d *Db) CreateUser(i *SignUpArgs) (User, error) {
var (
sqlStatement = `
INSERT INTO users (email, username, password)
VALUES ($1, $2, $3)
RETURNING user_id`
userID graphql.ID
row *sql.Row
err error
u User
)
/***************************************************************************
* retrieve the UserID of the newly inserted record
* db.Exec() requires the Result interface with the
LastInsertId() method which relies on a returned value from postgresQL
* lib/pq does not however return the last inserted record
****************************************************************************/
row = d.QueryRow(sqlStatement, i.Email, i.Username, i.Password)
if err = row.Scan(&userID); err != nil {
// err: username or email is not unqiue --> user already exsits
return u, err
}
err = row.Scan(
&u.UserID,
&u.Username,
&u.Email,
&u.Password,
)
util.Check(err, "row.Scan User")
return u, nil
}
didn't do it obviously. hence the question, why the query error? seems like UserResolver can't return the User data provided the row is being returned from db.
Your type definitions include:
type Mutation {
signUp(signUpInput: SignUpInput): SignUpResponse!
}
type SignUpResponse {
ok: Boolean!
error: String
addedUser: User
}
It appears you're attempting to query the fields for the returned User, but signUp does not return a User object. Instead, signUp returns a SignUpResponse object, which, as the error states, does not have any fields named email or username.
The correct query would look something like this:
mutation {
signUp(signUpInput: {email: "newuser#gmail.com", username: "newUser", password: "asdfasdfawerawer"}) {
addedUser {
email
username
}
ok
error
}
}

How to access struct with a variable?

I'm new to Go and I'm facing issues in accessing a struct with a variable
I have this function decodeUser. My task is to check whether the keys are present in the request. So this is what I did. I've added a comment where I got the error.
func decodeUser(r *http.Request) (root.User, []string, error) {
var u root.User
if r.Body == nil {
return u, []string{}, errors.New("no request body")
}
decoder := json.NewDecoder(r.Body)
checks := []string{
"UserName",
"FirstName",
"LastName",
"Email",
}
emptyFields := []string{}
for _, check := range checks {
// i'm having problem over here `u[check]` it's showing (invalid
operation: u[check] (type root.User does not support
indexing))
if u[check] == nil {
emptyFields = append(emptyFields, check)
}
}
err := decoder.Decode(&u)
return u, emptyFields, err
}
Just in case I added root.User here's structure for it
type User struct {
ID string
Username string
Password string
FirstName string
LastName string
Email string
PhoneNumber string
PhoneNumberExtension string
DOB time.Time
AboutMe string
}
The problem occurs as it doesn't allow me to access struct by a variable and I can't use this method which is u.check. So basically how should I make u[check] work?
I would suggest you manually check for zero values since it seems that you already know the fields that needs to be non-zero at compile time. However, if that is not the case, here is a simple function (using reflection) that will check for zero values in a struct.
func zeroFields(v interface{}, fields ...string) []string {
val := reflect.Indirect(reflect.ValueOf(v))
if val.Kind() != reflect.Struct {
return nil
}
var zeroes []string
for _, name := range fields {
field := val.FieldByName(name)
if !field.IsValid() {
continue
}
zero := reflect.Zero(field.Type())
// check for zero value
if reflect.DeepEqual(zero.Interface(), field.Interface()) {
zeroes = append(zeroes, name)
}
}
return zeroes
}
func main() {
x := User{
Email: "not#nil",
}
fmt.Println(zeroFields(&x, "ID", "Username", "Email", "Something", "DOB"))
}
Which would output:
[ID Username DOB]
Playground
This is what worked for me
for _, check := range checks {
temp := reflect.Indirect(reflect.ValueOf(&u))
fieldValue := temp.FieldByName(string(check))
if (fieldValue.Type().String() == "string" && fieldValue.Len() == 0) || (fieldValue.Type().String() != "string" && fieldValue.IsNil()) {
fmt.Println("EMPTY->", check)
emptyFields = append(emptyFields, check)
}
}

How to match all user_name with password in golang?

Using a struct, I'm saving the data in the JSON form to collection like so:
type SignUp struct {
Id int `json:"_id" bson:"_id"`
UserName string `json:"user_name" bson:"user_name"`
EmailId string `json:"email_id" bson:"email_id"`
Password string `json:"password" bson:"password"`
}
type SignUps []SignUp
And retrieved the data from the collection of mongodb using function
func Login(c *gin.Context) {
response := ResponseControllerList{}
conditions := bson.M{}
data, err := GetAllUser(conditions)
fmt.Println(data)
fmt.Println(err)
Matching(data)
return
}
func GetAllUser(blogQuery interface{}) (result SignUps, err error) {
mongoSession := config.ConnectDb()
sessionCopy := mongoSession.Copy()
defer sessionCopy.Close()
getCollection := mongoSession.DB("sign").C("signup")
err = getCollection.Find(blogQuery).Select(bson.M{}).All(&result)
if err != nil {
return result, err
}
return result, nil
}
But the data retrieved without its keys like shown below:-
[{1 puneet puneet#gmail.com puneet} {2 Rohit abc#gmail.com puneet}]
Issue is that I want to collect all the existing EmailId and Password
and match them with userid and password entered by the user in fucntion given bellow:-
func Matching(data Signups){
userid="abc#gmail.com"
password="puneet"
//match?
}
How can I match the userid and password with the EmailId and Password fields?
This is not answering your question directly, but is very important nonetheless. It seems that you are saving the passwords of your users in plain text in the database. This is very careless and you should add some encryption like bcrypt: https://godoc.org/golang.org/x/crypto/bcrypt
When you have added some encryption, your matching would be quite different than all given answers. This depends on the used encryption package. But please ignore the other answers. They might work, but only for plain text passwords.
You can give an if condition to check if the userid or email is empty or not on your Matching function like:
....
if data.userid != "" {
data.username = data.userid
}
data.password
....
You can create new struct for the query and use it to create your Matching function.
for _, signup := range data {
if userId == signup.Id && password == signup.Password {
println("Match!")
}
}

Golang Structs/Interfaces

I'm trying to do something to bring the SQL results dynamically structure, basically I want to run a function by passing the rows and the structure(to get the data type and make one) and return in interface array.
Anyone know how I can do?
I dont want pass the direct "User" struct as param.. that is not dynamically
type User struct{
Id_user int `json:"id_user"`
Name string `json:"name"`
Email string `json:"email"`
Username string `json: "username"`
}
func main() {
var user User
rows, _ := db.Query("SELECT id_user, name, email, username FROM users")
json.NewEncoder(w).Encode(StructRow(user, rows))
}
func StructRow(u interface{}, rows *sql.Rows)[]interface{}{
var data []interface{}
for rows.Next() {
//How i can create a "user" here, dynamically
//for Example
//var user reflect.TypeOf(u)
_ = rows.Scan(StrutForScan(&user)...)
data = append(data, user)
}
return data
}
func StrutForScan(u interface{}) []interface{} {
val := reflect.ValueOf(u).Elem()
v := make([]interface{}, val.NumField())
for i := 0; i < val.NumField(); i++ {
valueField := val.Field(i)
v[i] = valueField.Addr().Interface()
}
return v
}
Changing your function StructRow to
func StructRow(u interface{}, rows *sql.Rows) []interface{} {
var data []interface{}
for rows.Next() {
t := reflect.TypeOf(u)
val := reflect.New(t).Interface()
errScan := rows.Scan(StrutForScan(val)...)
if errScan != nil {
//proper err handling
}
data = append(data, val)
}
return data
}
will fix it. I guess.
For more on reflect package go to: https://golang.org/pkg/reflect/

Martini session not moving between requests

I am writing a web app using the martini-contrib session library. I seem to have run into an issue though. My session don't seem to be moving between requests in the browser.
I have followed the exact guidelines that were outline in the example code, yet my code does not work. Below is the pertinent parts:
Login page:
m.Get("/login", binding.Bind(LoginForm{}), func(r render.Render, session sessions.Session, form LoginForm) string {
// Get info from the database.
conn, err := sql.Open("sqlite3", "ocdns.db")
defer conn.Close()
// Prepare the statement.
stmt, err := conn.Prepare(`
SELECT user_id, username, name_first, name_last, role, team_id
FROM User
WHERE username = ? AND password = ?
LIMIT 1;
`)
if err != nil {
log.Fatal(err)
}
defer stmt.Close()
// Query the database and set appropriate items if a row was actually returned.
var id string
var username string
var name_first string
var name_last string
var role string
var team_id string
err = stmt.QueryRow(form.Username, form.Password).Scan(&id, &username, &name_first, &name_last, &role, &team_id)
if err != nil {
log.Print("!! Bad login from " + form.Username + " with " + form.Password)
log.Fatal(err)
} else {
log.Print(">" + id + "<")
log.Print(">" + username + "<")
log.Print(">" + name_first + "<")
log.Print(">" + name_last + "<")
log.Print(">" + role + "<")
log.Print(">" + team_id + "<")
session.Set("id", id)
session.Set("username", username)
session.Set("name_first", name_first)
session.Set("name_last", name_last)
session.Set("role", role)
session.Set("team_id", team_id)
v := session.Get("name_first")
if v == nil {
log.Print("!! Uh oh.")
}
log.Print(v.(string))
return "OK"
}
return "Bad"
})
Session check page:
m.Get("/session", func(session sessions.Session) string {
var c Context
i := session.Get("id")
if i == nil {
c.Id = -1
}
c.Id, _ = strconv.Atoi(i.(string))
i = session.Get("username")
if i == nil {
log.Print("!! username")
}
if vs, ok := i.(string); ok {
c.Username = vs
} else {
log.Print(vs)
}
log.Print(c)
j, _ := json.Marshal(c)
return string(j)
})
Context struct:
type Context struct {
Id int `json:"id"`
Username string `json:"username"`
NameFirst string `json:"name_first"`
NameLast string `json:"name_last"`
Role string `json:"role"`
TeamId int `json:"team_id"`
}
Finally, my session declaration:
// Create session store.
store := sessions.NewCookieStore([]byte("secret123"))
m.Use(sessions.Sessions("my_session", store))
I have tried emptying my cache to get it to work, but it won't. I did look in Chrome's developer tools to see if storage was being used and I did find that the session moved between two pages, but the output of the session request was an empty Context json stucture.
What I need is to figure out why my session data seems to be getting lost between requests and what I can do to fix it. I have looked on here and while nothing fits my exact problem, I did find that there were ones that had problems with their web server configuration.
Thanks in advance!
You should change your first function call as follow to make sure it must goto session first before login.
m.Get("/login", SOME_FUNC_TO_SEESION, func(r render.Render, session sessions.Session, form LoginForm) string {
Here is sample video, hope it help you. Your code should work well.
https://gophercasts.io/lessons/8-auth-part-2

Resources