'How to pass foreign key in Golang gin gracefully

It's werid our project's foreign key is name, not id, I am very new to Golang, I have a problem to change our api of POST, When I would like to POST a user with url of http://127.0.0.1:8080/project/3/user

by this json, { "project": "project3", "password": "alice", "username": "alice" }

parameter of project is required, and if I type wrong project name, I will get below error:

"error": "Error 1452: Cannot add or update a child row: a foreign key constraint fails (`test_project`.`users`, CONSTRAINT `project_ibfk_1` FOREIGN KEY (`project`) REFERENCES `projects` (`name`) ON DELETE RESTRICT ON UPDATE CASCADE)"

In my experience, parameter of project is no need, because url http://127.0.0.1:8080/project/3/user already contain project ID, we don't need to post project name, but according to current table and code, I don't know how to change this. Thanks so much for any advice.

And below is user.go

package projects

import (
    "test_project/pkg/query"
    "time"
)

type User struct {
    Id        string    `gorm:"index:,unique" json:"id"`
    Project   string    `json:"project" binding:"required"`
    Username  string    `json:"username" binding:"required"`
    Password  string    `json:"password"`
    CreatedTime time.Time `json:"created_time"`
    UpdatedTime time.Time `json:"updated_time"`
}

type UserRepository interface {
    Create(User) error
    Update(User) error
    RetrieveById(id string) (User, error)
    RetrieveByName(project string, name string) (User, error)
    RetrieveAll(name string, q query.RetrieveBody) (query.RetrieveRes, error)
    Delete(id string) error
}

Below is user_service.go

package projects

import (
    "test_project/auth"
    "test_project/pkg/query"
    "net/http"
    "github.com/gin-gonic/gin"
    "github.com/google/uuid"
)

type UsersService interface {
    Register(context *gin.Context)
}


func (svc projectService) Register(context *gin.Context) {
    project_id := context.Param("project_id")

    var user User
    if err := context.ShouldBindJSON(&user); err != nil {
        context.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
        return
    }

    // generate a uuid
    id, err := uuid.NewRandom()
    if err != nil {
        context.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "failed to generate uuid"})
        return
    }
    user.Id = id.String()

    // create a user
    if err := svc.users.Create(user); err != nil {
        context.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
        return
    }
    context.Status(http.StatusCreated)
}

And Below is route.go

package router

import (
    "test_project/projects"
    "test_project/pkg/security"
    "github.com/gin-gonic/gin"
)

func MyRouter(svc projects.Service) *gin.Engine {
    s := security.New(client)

    router := gin.New()
    router.Use(logger.GinLogger(), logger.GinRecovery(true))

    users := router.Group("projects/:project_id")
    {
        users.POST("users", s.WriteAccess("project_id"), svc.Register)
        users.GET("users", s.ReadAccess("project_id"), svc.ListUsers)
    }

    return router
}

Below is my two tables

CREATE TABLE IF NOT EXISTS projects(
    id                  CHAR(36) PRIMARY KEY,
    name                VARCHAR(255) NOT NULL UNIQUE,
    status              INT DEFAULT 0,
    created_time          TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_time          TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP);
    
CREATE TABLE IF NOT EXISTS users(
    id          CHAR(36) PRIMARY KEY,
    project     VARCHAR(255) NOT NULL,
    username    VARCHAR(255) NOT NULL,
    password    VARCHAR(255) NOT NULL,
    created_time  TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_time  TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    CONSTRAINT project_user UNIQUE (project, username),
    FOREIGN KEY (project) REFERENCES projects(name) ON DELETE RESTRICT ON UPDATE CASCADE
);

And below is the data of users

select * from users;
---------------------------------------------------------
1   project1    amy project1    2022-03-23 10:04:03 2022-03-25 10:26:07
2   project2    mike    project2    2022-03-22 16:43:44 2022-03-25 10:25:29
3   project3    anna    project3    2022-03-23 09:26:14 2022-03-25 10:26:23
go


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source