こんにちは、KOUKIです。
GolangのWebフレームワークである、fiberを使ってAPIを開発しています。
前回は、Middlewareの実装方法を紹介しました。
今回は、プロファイル(ユーザー情報やパスワード)の情報を更新する処理を実装します。
尚、Udemyの「React, NextJS and Golang: A Rapid Guide – Advanced」コースを参考にしています。解釈は私が勝手に付けているので、本物をみたい場合は受講をお勧めします!
前回
作るもの
認証機能を作りたいと思います。エンドポイントは、次の通りです。
- POST /api/admin/register
- POST /api/admin/login
- POST /api/admin/logout
- GET /api/admin/user
- PUT /api/admin/users/info
- PUT /api/admin/users/password
今回は、「/api/admin/users/info」と「/api/admin/users/password」へのリクエストを実装します。
ユーザー情報の更新
ユーザー情報の更新処理を実装しましょう。
ルートの追加
「/api/admin/users/info」へのルートを追加します。
1 2 3 4 5 6 7 8 9 |
// routes/routes.go package routes ... func Setup(app *fiber.App) { ... // Middleware ... adminAuthenticated.Put("info", controllers.UpdateInfo) // 追加 } |
前回実装したMiddlewareからルートを割り当てていることに注意してください。これにより、アクセスするたびにログイン済みか否かをチェックしています。
コントローラーの追加
次に、コントローラーを追加しましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
func UpdateInfo(ctx *fiber.Ctx) error { var data map[string]string // リクエストデータをパースする if err := ctx.BodyParser(&data); err != nil { return err } // cookieからidを取得する id, _ := middleware.GetUserID(ctx) user := models.User{ ID: id, FirstName: data["first_name"], LastName: data["last_name"], Email: data["email"], } // ユーザー情報更新 database.DB.Model(&user).Updates(&user) return ctx.JSON(user) } |
これでユーザー情報が更新できるようになったはずです。
検証
ユーザー情報が更新できるか確認しましょう。これを確かめるには、ログインしていることが前提です。
1 |
docker-compose up |
- URL: http://localhost:8000/api/admin/info
- 形式:PUT
1 2 3 4 5 |
{ "first_name": "self_update", "last_name": "note_update", "email": "self_update@ne.jp" } |

OKですね。一応DBも確認しておきましょう。

updateされていることが確認できました。
パスワードの更新
続いて、パスワードの更新処理を実装しましょう。
ルートの追加
「/api/admin/users/password」へのパスを追加します。
1 2 3 4 5 6 7 8 9 |
// routes/routes.go ... func Setup(app *fiber.App) { ... // Middleware ... adminAuthenticated.Put("password", controllers.UpdatePassword) // 追加 } |
コントローラーの追加
コントローラーを追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
// controllers/auathController.go func UpdatePassword(ctx *fiber.Ctx) error { var data map[string]string // リクエストデータをパースする if err := ctx.BodyParser(&data); err != nil { return err } // パスワードチェック if data["password"] != data["password_confirm"] { ctx.Status(fiber.StatusBadRequest) // 400 return ctx.JSON(fiber.Map{ "message": "パスワードに誤りがあります", }) } // cookieからidを取得する id, _ := middleware.GetUserID(ctx) user := models.User{ ID: id, } // パスワードセット user.SetPassword(data["password"]) // ユーザー情報更新 database.DB.Model(&user).Updates(&user) return ctx.JSON(user) } |
検証
まずは、以下のパラメータでログインできることを確認しましょう。
ログイン
- URL: http://localhost:8000/api/admin/login
- 形式: POST
1 2 3 4 |
{ "email": "self@ne.jp", "password": "a" } |
パスワード更新
ログインに成功したらパスワードの更新を行います。
- URL: http://localhost:8000/api/admin/password
- 形式: PUT
1 2 3 4 |
{ "password": "b", "password_confirm": "b" } |

OKですね。
ログイン2
再設定パスワードでログインしてみましょう。
- URL: http://localhost:8000/api/admin/login
- 形式: POST
1 2 3 4 |
{ "email": "self@ne.jp", "password": "b" } |

OKですね。
次回
次回は、ユーザーデータの取得処理を実装します。
Go言語まとめ
ソースコード
ここまでのソースコードを以下に記載します。
auathController.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
// controllers/auathController.go package controllers import ( "admin/src/database" "admin/src/middleware" "admin/src/models" "strconv" "time" "github.com/dgrijalva/jwt-go" "github.com/gofiber/fiber/v2" "golang.org/x/crypto/bcrypt" ) func Register(ctx *fiber.Ctx) error { var data map[string]string if err := ctx.BodyParser(&data); err != nil { return err } if data["password"] != data["password_confirm"] { ctx.Status(fiber.StatusBadRequest) // 400 return ctx.JSON(fiber.Map{ "message": "パスワードに誤りがあります", }) } // ハッシュパスワードを作成 pwd, _ := bcrypt.GenerateFromPassword([]byte(data["password"]), 12) user := models.User{ FirstName: data["first_name"], LastName: data["last_name"], Email: data["email"], Password: pwd, IsAmbassdor: false, } // パスワードセット user.SetPassword(data["password"]) // ユーザー作成 result := database.DB.Create(&user) if result.Error != nil { ctx.Status(fiber.StatusBadRequest) return ctx.JSON(fiber.Map{ "message": "そのEmailは既に登録されています", }) } return ctx.JSON(user) } func Login(ctx *fiber.Ctx) error { var data map[string]string if err := ctx.BodyParser(&data); err != nil { return err } var user models.User database.DB.Where("email = ?", data["email"]).First(&user) if user.ID == 0 { ctx.Status(fiber.StatusBadRequest) return ctx.JSON(fiber.Map{ "message": "ログイン情報に誤りがあります", }) } // パスワードチェック err := user.ComparePassword(data["password"]) if err != nil { ctx.Status(fiber.StatusBadRequest) return ctx.JSON(fiber.Map{ "message": "ログイン情報に誤りがあります", }) } // トークンの発行 payload := jwt.StandardClaims{ Subject: strconv.Itoa(int(user.ID)), ExpiresAt: time.Now().Add(time.Hour * 24).Unix(), } token, err := jwt.NewWithClaims(jwt.SigningMethodHS256, payload).SignedString([]byte("secret")) if err != nil { ctx.Status(fiber.StatusBadRequest) return ctx.JSON(fiber.Map{ "message": "ログイン情報に誤りがあります", }) } // Cookieに保存 cookie := fiber.Cookie{ Name: "jwt", Value: token, Expires: time.Now().Add(time.Hour * 24), HTTPOnly: true, } ctx.Cookie(&cookie) return ctx.JSON(fiber.Map{ "message": "success", }) } func User(ctx *fiber.Ctx) error { id, _ := middleware.GetUserID(ctx) // ユーザー検索 var user models.User database.DB.Where("id = ?", id).First(&user) return ctx.JSON(user) } func Logout(ctx *fiber.Ctx) error { // cookieをクリアする cookie := fiber.Cookie{ Name: "jwt", Value: "", Expires: time.Now().Add(-time.Hour * 24), // -を指定 HTTPOnly: true, } ctx.Cookie(&cookie) return ctx.JSON(fiber.Map{ "message": "success", }) } func UpdateInfo(ctx *fiber.Ctx) error { var data map[string]string // リクエストデータをパースする if err := ctx.BodyParser(&data); err != nil { return err } // cookieからidを取得する id, _ := middleware.GetUserID(ctx) user := models.User{ ID: id, FirstName: data["first_name"], LastName: data["last_name"], Email: data["email"], } // ユーザー情報更新 database.DB.Model(&user).Updates(&user) return ctx.JSON(user) } func UpdatePassword(ctx *fiber.Ctx) error { var data map[string]string // リクエストデータをパースする if err := ctx.BodyParser(&data); err != nil { return err } // パスワードチェック if data["password"] != data["password_confirm"] { ctx.Status(fiber.StatusBadRequest) // 400 return ctx.JSON(fiber.Map{ "message": "パスワードに誤りがあります", }) } // cookieからidを取得する id, _ := middleware.GetUserID(ctx) user := models.User{ ID: id, } // パスワードセット user.SetPassword(data["password"]) // ユーザー情報更新 database.DB.Model(&user).Updates(&user) return ctx.JSON(user) } |
routes.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
// routes/routes.go package routes import ( "admin/src/controllers" "admin/src/middleware" "github.com/gofiber/fiber/v2" ) func Setup(app *fiber.App) { // GROUP api := app.Group("api") admin := api.Group("admin") // No Middleware admin.Post("register", controllers.Register) admin.Post("login", controllers.Login) // Middleware adminAuthenticated := admin.Use(middleware.IsAuthenticate) adminAuthenticated.Get("user", controllers.User) adminAuthenticated.Post("logout", controllers.Logout) adminAuthenticated.Put("info", controllers.UpdateInfo) adminAuthenticated.Put("password", controllers.UpdatePassword) } |
コメントを残す
コメントを投稿するにはログインしてください。