feat: update
This commit is contained in:
@@ -12,7 +12,6 @@ import (
|
||||
"quyun/providers/jwt"
|
||||
"quyun/providers/wechat"
|
||||
|
||||
"github.com/go-jet/jet/v2/qrm"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
gonanoid "github.com/matoous/go-nanoid/v2"
|
||||
"github.com/pkg/errors"
|
||||
@@ -51,24 +50,31 @@ func (ctl *auth) Login(ctx fiber.Ctx, code, state, redirect string) error {
|
||||
|
||||
log.Debugf("Auth User Info: %+v", authUserInfo)
|
||||
|
||||
user, err := models.Users.GetUserByOpenID(ctx.Context(), token.Openid)
|
||||
userModel := &model.Users{
|
||||
Status: fields.UserStatusOk,
|
||||
OpenID: token.GetOpenID(),
|
||||
Username: fmt.Sprintf("u_%s", gonanoid.MustGenerate(salt, 8)),
|
||||
Avatar: nil,
|
||||
Metas: fields.ToJson(fields.UserMetas{
|
||||
City: authUserInfo.City,
|
||||
Country: authUserInfo.Country,
|
||||
HeadImageUrl: authUserInfo.Headimgurl,
|
||||
Nickname: authUserInfo.Nickname,
|
||||
Privilege: authUserInfo.Privilege,
|
||||
Province: authUserInfo.Province,
|
||||
Sex: authUserInfo.Sex,
|
||||
}),
|
||||
AuthToken: fields.ToJson(fields.UserAuthToken{
|
||||
AccessToken: token.AccessToken,
|
||||
ExpiresAt: time.Now().Add(time.Second * time.Duration(token.ExpiresIn)),
|
||||
IsSnapshotuser: token.IsSnapshotuser,
|
||||
RefreshToken: token.RefreshToken,
|
||||
Scope: token.Scope,
|
||||
}),
|
||||
}
|
||||
user, err := models.Users.GetUserByOpenIDOrCreate(ctx.Context(), token.Openid, userModel)
|
||||
if err != nil {
|
||||
if errors.Is(err, qrm.ErrNoRows) {
|
||||
// Create User
|
||||
model := &model.Users{
|
||||
Status: fields.UserStatusOk,
|
||||
OpenID: token.GetOpenID(),
|
||||
Username: fmt.Sprintf("u_%s", gonanoid.MustGenerate(salt, 8)),
|
||||
Avatar: nil,
|
||||
}
|
||||
|
||||
user, err = models.Users.Create(ctx.Context(), model)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to create user")
|
||||
}
|
||||
} else {
|
||||
return errors.Wrap(err, "failed to get user")
|
||||
}
|
||||
return errors.Wrap(err, "failed to get user by openid")
|
||||
}
|
||||
|
||||
jwtToken, err := ctl.jwt.CreateToken(ctl.jwt.CreateClaims(jwt.BaseClaims{UserID: user.ID}))
|
||||
|
||||
@@ -2,7 +2,6 @@ package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"quyun/app/requests"
|
||||
@@ -11,6 +10,7 @@ import (
|
||||
|
||||
. "github.com/go-jet/jet/v2/postgres"
|
||||
"github.com/go-jet/jet/v2/qrm"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/samber/lo"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
@@ -272,6 +272,24 @@ func (m *usersModel) GetUserByOpenID(ctx context.Context, openID string) (*model
|
||||
return &user, nil
|
||||
}
|
||||
|
||||
// GetUserByOpenIDOrCreate
|
||||
func (m *usersModel) GetUserByOpenIDOrCreate(ctx context.Context, openID string, userModel *model.Users) (*model.Users, error) {
|
||||
user, err := m.GetUserByOpenID(ctx, openID)
|
||||
if err != nil {
|
||||
if errors.Is(err, qrm.ErrNoRows) {
|
||||
// Create User
|
||||
|
||||
user, err = m.Create(ctx, userModel)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to create user")
|
||||
}
|
||||
} else {
|
||||
return nil, errors.Wrap(err, "failed to get user")
|
||||
}
|
||||
}
|
||||
return user, nil
|
||||
}
|
||||
|
||||
// GetUsersMapByIDs
|
||||
func (m *usersModel) GetUsersMapByIDs(ctx context.Context, ids []int64) (map[int64]model.Users, error) {
|
||||
if len(ids) == 0 {
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
Mode = "development"
|
||||
BaseURI = "baseURI"
|
||||
StoragePath = "/Users/rogee/Projects/self/quyun/fixtures"
|
||||
DistAdmin = "/app/dist/admin"
|
||||
DistWeChat = "/app/dist/wechat"
|
||||
DistAdmin = "frontend/wechat/admin"
|
||||
DistWeChat = "frontend/wechat/dist"
|
||||
|
||||
[Http]
|
||||
Port = 8088
|
||||
|
||||
@@ -1,5 +1,25 @@
|
||||
package fields
|
||||
|
||||
import "time"
|
||||
|
||||
// swagger:enum PostStatus
|
||||
// ENUM( ok, banned, blocked)
|
||||
type UserStatus int16
|
||||
|
||||
type UserMetas struct {
|
||||
City string `json:"city,omitempty"`
|
||||
Country string `json:"country,omitempty"`
|
||||
HeadImageUrl string `json:"head_image_url,omitempty"`
|
||||
Nickname string `json:"nickname,omitempty"`
|
||||
Privilege []string `json:"privilege,omitempty"`
|
||||
Province string `json:"province,omitempty"`
|
||||
Sex int64 `json:"sex,omitempty"`
|
||||
}
|
||||
|
||||
type UserAuthToken struct {
|
||||
AccessToken string `json:"access_token,omitempty"`
|
||||
ExpiresAt time.Time `json:"expires_at,omitempty"`
|
||||
IsSnapshotuser int64 `json:"is_snapshotuser,omitempty"`
|
||||
RefreshToken string `json:"refresh_token,omitempty"`
|
||||
Scope string `json:"scope,omitempty"`
|
||||
}
|
||||
|
||||
18
backend/database/migrations/20250430014015_alter_user.sql
Normal file
18
backend/database/migrations/20250430014015_alter_user.sql
Normal file
@@ -0,0 +1,18 @@
|
||||
-- +goose Up
|
||||
-- +goose StatementBegin
|
||||
ALTER TABLE public.users
|
||||
ADD metas jsonb DEFAULT '{}'::jsonb NOT NULL;
|
||||
|
||||
ALTER TABLE public.users
|
||||
ADD auth_token jsonb DEFAULT '{}'::jsonb NOT NULL;
|
||||
|
||||
-- +goose StatementEnd
|
||||
-- +goose Down
|
||||
-- +goose StatementBegin
|
||||
ALTER TABLE public.users
|
||||
DROP COLUMN metas;
|
||||
|
||||
ALTER TABLE public.users
|
||||
DROP COLUMN auth_token;
|
||||
|
||||
-- +goose StatementEnd
|
||||
@@ -13,12 +13,14 @@ import (
|
||||
)
|
||||
|
||||
type Users struct {
|
||||
ID int64 `sql:"primary_key" json:"id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
DeletedAt *time.Time `json:"deleted_at"`
|
||||
Status fields.UserStatus `json:"status"`
|
||||
OpenID string `json:"open_id"`
|
||||
Username string `json:"username"`
|
||||
Avatar *string `json:"avatar"`
|
||||
ID int64 `sql:"primary_key" json:"id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
DeletedAt *time.Time `json:"deleted_at"`
|
||||
Status fields.UserStatus `json:"status"`
|
||||
OpenID string `json:"open_id"`
|
||||
Username string `json:"username"`
|
||||
Avatar *string `json:"avatar"`
|
||||
Metas fields.Json[fields.UserMetas] `json:"metas"`
|
||||
AuthToken fields.Json[fields.UserAuthToken] `json:"auth_token"`
|
||||
}
|
||||
|
||||
@@ -25,6 +25,8 @@ type usersTable struct {
|
||||
OpenID postgres.ColumnString
|
||||
Username postgres.ColumnString
|
||||
Avatar postgres.ColumnString
|
||||
Metas postgres.ColumnString
|
||||
AuthToken postgres.ColumnString
|
||||
|
||||
AllColumns postgres.ColumnList
|
||||
MutableColumns postgres.ColumnList
|
||||
@@ -73,8 +75,10 @@ func newUsersTableImpl(schemaName, tableName, alias string) usersTable {
|
||||
OpenIDColumn = postgres.StringColumn("open_id")
|
||||
UsernameColumn = postgres.StringColumn("username")
|
||||
AvatarColumn = postgres.StringColumn("avatar")
|
||||
allColumns = postgres.ColumnList{IDColumn, CreatedAtColumn, UpdatedAtColumn, DeletedAtColumn, StatusColumn, OpenIDColumn, UsernameColumn, AvatarColumn}
|
||||
mutableColumns = postgres.ColumnList{CreatedAtColumn, UpdatedAtColumn, DeletedAtColumn, StatusColumn, OpenIDColumn, UsernameColumn, AvatarColumn}
|
||||
MetasColumn = postgres.StringColumn("metas")
|
||||
AuthTokenColumn = postgres.StringColumn("auth_token")
|
||||
allColumns = postgres.ColumnList{IDColumn, CreatedAtColumn, UpdatedAtColumn, DeletedAtColumn, StatusColumn, OpenIDColumn, UsernameColumn, AvatarColumn, MetasColumn, AuthTokenColumn}
|
||||
mutableColumns = postgres.ColumnList{CreatedAtColumn, UpdatedAtColumn, DeletedAtColumn, StatusColumn, OpenIDColumn, UsernameColumn, AvatarColumn, MetasColumn, AuthTokenColumn}
|
||||
)
|
||||
|
||||
return usersTable{
|
||||
@@ -89,6 +93,8 @@ func newUsersTableImpl(schemaName, tableName, alias string) usersTable {
|
||||
OpenID: OpenIDColumn,
|
||||
Username: UsernameColumn,
|
||||
Avatar: AvatarColumn,
|
||||
Metas: MetasColumn,
|
||||
AuthToken: AuthTokenColumn,
|
||||
|
||||
AllColumns: allColumns,
|
||||
MutableColumns: mutableColumns,
|
||||
|
||||
@@ -21,6 +21,8 @@ types:
|
||||
|
||||
users:
|
||||
status: UserStatus
|
||||
metas: Json[UserMetas]
|
||||
auth_token: Json[UserAuthToken]
|
||||
|
||||
orders:
|
||||
status: OrderStatus
|
||||
|
||||
@@ -3,9 +3,8 @@
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Hello</title>
|
||||
<title>动态曲谱</title>
|
||||
<link href="/src/styles.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>
|
||||
|
Before Width: | Height: | Size: 496 B |
Reference in New Issue
Block a user