Skip to content

Commit

Permalink
feat: remove use of register_email and delete_email table, use `i…
Browse files Browse the repository at this point in the history
…dx_user_identifier` index and `delete_identifier` table instead;

DeleteByUserID
fix: when standalone call kong, nil pointer reference panic
  • Loading branch information
JingYiJun committed Jul 30, 2023
1 parent e877cb2 commit 148c18b
Show file tree
Hide file tree
Showing 10 changed files with 216 additions and 109 deletions.
117 changes: 79 additions & 38 deletions apis/account.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package apis

import (
"database/sql"
"fmt"
"runtime"

Expand Down Expand Up @@ -103,16 +104,16 @@ func RegisterDebugInBatch(c *fiber.Ctx) (err error) {
// check registered
var emailHashes []string
for _, data := range body.Data {
emailHashes = append(emailHashes, Sha3SumEmail(data.Email))
emailHashes = append(emailHashes, auth.MakeIdentifier(data.Email))
}

var count int64
err = DB.Model(&RegisteredEmail{}).Where("hash IN ?", emailHashes).Count(&count).Error
var exists bool
err = DB.Raw(`SELECT EXISTS (SELECT 1 FROM user WHERE identifier IN (?))`, emailHashes).Scan(&exists).Error
if err != nil {
return err
}

if count > 0 {
if exists {
return common.BadRequest("用户已注册")
}

Expand Down Expand Up @@ -151,7 +152,7 @@ func RegisterDebugInBatch(c *fiber.Ctx) (err error) {
tasksChan <- func() {
var user User
user.Email = data.Email
user.Identifier = auth.MakeIdentifier(data.Email)
user.Identifier = sql.NullString{String: auth.MakeIdentifier(data.Email), Valid: true}
user.Password, err = auth.MakePassword(data.Password)
if err != nil {
errChan <- err
Expand Down Expand Up @@ -187,21 +188,6 @@ func RegisterDebugInBatch(c *fiber.Ctx) (err error) {

log.Info().Str("scope", taskScope).Msgf("create users: %d", len(users))

// create registered emails
var registeredEmails []RegisteredEmail
for _, hash := range emailHashes {
registeredEmails = append(registeredEmails, RegisteredEmail{
Hash: hash,
})
}

err = tx.Create(&registeredEmails).Error
if err != nil {
return err
}

log.Info().Str("scope", taskScope).Msgf("create registered emails: %d", len(registeredEmails))

if config.Config.ShamirFeature {

// create shamir emails
Expand Down Expand Up @@ -294,7 +280,7 @@ func register(c *fiber.Ctx, email, password string, batch bool) error {

// not registered

user.Identifier = auth.MakeIdentifier(email)
user.Identifier = sql.NullString{String: auth.MakeIdentifier(email), Valid: true}
user.Password, err = auth.MakePassword(password)
if err != nil {
return err
Expand All @@ -310,11 +296,6 @@ func register(c *fiber.Ctx, email, password string, batch bool) error {
return err
}

err = AddRegisteredEmail(tx, email)
if err != nil {
return err
}

// create shamir emails
if config.Config.ShamirFeature {
return CreateShamirEmails(tx, user.ID, email)
Expand Down Expand Up @@ -597,8 +578,8 @@ func VerifyWithApikey(c *fiber.Ctx) error {
// @Router /users/me [delete]
// @Param json body LoginRequest true "email, password"
// @Success 204
// @Failure 400 {object} common.MessageResponse "密码错误
// @Failure 404 {object} common.MessageResponse "用户不存在
// @Failure 400 {object} common.MessageResponse "密码错误"
// @Failure 404 {object} common.MessageResponse "用户不存在"
// @Failure 500 {object} common.MessageResponse
func DeleteUser(c *fiber.Ctx) error {
var body LoginRequest
Expand All @@ -617,6 +598,10 @@ func DeleteUser(c *fiber.Ctx) error {
return err
}

if !user.Identifier.Valid {
return common.BadRequest("账户已注销")
}

ok, err := auth.CheckPassword(body.Password, user.Password)
if err != nil {
return err
Expand All @@ -625,27 +610,83 @@ func DeleteUser(c *fiber.Ctx) error {
return common.Forbidden("密码错误")
}

err = AddDeletedIdentifier(tx, user.UserID, user.Identifier)
return DeleteUserService(tx, user.ID, user.Identifier.String)
})

if err != nil {
return err
}

// delete jwt credentials
if !config.Config.Standalone {
userID := user.ID
go func() {
err = kong.DeleteJwtCredential(userID)
if err != nil {
log.Warn().Err(err).Int("user_id", userID).Msg("failed to delete jwt credential")
}
}()
}

return c.SendStatus(204)
}

// DeleteUserByID godoc
//
// @Summary delete user by id, admin only
// @Description delete user and related jwt credentials
// @Tags account
// @Router /users/{id} [delete]
// @Param id path int true "user id"
// @Success 204
// @Failure 404 {object} common.MessageResponse "用户不存在"
// @Failure 500 {object} common.MessageResponse
func DeleteUserByID(c *fiber.Ctx) error {
operatorID, err := common.GetUserID(c)
if err != nil {
return err
}
if !IsAdmin(operatorID) {
return common.Forbidden()
}

userID, err := c.ParamsInt("id")
if err != nil {
return err
}

if operatorID == userID {
return common.Forbidden("不能注销自己")
}

var user User
err = DB.Transaction(func(tx *gorm.DB) error {
err = tx.
Clauses(clause.Locking{Strength: "UPDATE"}).
Where("id = ?", userID).
Take(&user).Error
if err != nil {
return err
}

err = tx.Model(&User{}).Where("id=?", user.ID).
UpdateColumns(map[string]interface{}{"is_active": false, "identifier": nil}).Error
if err != nil {
return err
if !user.Identifier.Valid {
return common.BadRequest("账户已注销")
}

return AddDeletedEmail(tx, body.Email)
return DeleteUserService(tx, user.ID, user.Identifier.String)
})

if err != nil {
return err
}

err = kong.DeleteJwtCredential(user.ID)
if err != nil {
return err
// delete jwt credentials
if !config.Config.Standalone {
go func() {
err = kong.DeleteJwtCredential(userID)
if err != nil {
log.Warn().Err(err).Int("user_id", userID).Msg("failed to delete jwt credential")
}
}()
}

return c.SendStatus(204)
Expand Down
1 change: 1 addition & 0 deletions apis/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ func RegisterRoutes(app *fiber.App) {
routes.Post("/register", Register)
routes.Put("/register", ChangePassword)
routes.Delete("/users/me", DeleteUser)
routes.Delete("/users/:id", DeleteUserByID)

// register questions
if config.Config.EnableRegisterQuestions {
Expand Down
39 changes: 37 additions & 2 deletions docs/docs.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

39 changes: 37 additions & 2 deletions docs/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -855,13 +855,48 @@
"description": "No Content"
},
"400": {
"description": "密码错误",
"description": "密码错误",
"schema": {
"$ref": "#/definitions/common.MessageResponse"
}
},
"404": {
"description": "用户不存在“",
"description": "用户不存在",
"schema": {
"$ref": "#/definitions/common.MessageResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/common.MessageResponse"
}
}
}
}
},
"/users/{id}": {
"delete": {
"description": "delete user and related jwt credentials",
"tags": [
"account"
],
"summary": "delete user by id, admin only",
"parameters": [
{
"type": "integer",
"description": "user id",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"204": {
"description": "No Content"
},
"404": {
"description": "用户不存在",
"schema": {
"$ref": "#/definitions/common.MessageResponse"
}
Expand Down
27 changes: 25 additions & 2 deletions docs/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -840,6 +840,29 @@ paths:
summary: list all users
tags:
- user
/users/{id}:
delete:
description: delete user and related jwt credentials
parameters:
- description: user id
in: path
name: id
required: true
type: integer
responses:
"204":
description: No Content
"404":
description: 用户不存在
schema:
$ref: '#/definitions/common.MessageResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/common.MessageResponse'
summary: delete user by id, admin only
tags:
- account
/users/{user_id}:
get:
description: get user by id in path, owner or admin
Expand Down Expand Up @@ -929,11 +952,11 @@ paths:
"204":
description: No Content
"400":
description: 密码错误
description: 密码错误
schema:
$ref: '#/definitions/common.MessageResponse'
"404":
description: 用户不存在
description: 用户不存在
schema:
$ref: '#/definitions/common.MessageResponse'
"500":
Expand Down
Loading

0 comments on commit 148c18b

Please sign in to comment.