mirror of
https://github.com/aykhans/slash-e.git
synced 2025-04-20 22:07:15 +00:00
chore: add user.open_id
field
This commit is contained in:
parent
0ba7a9e519
commit
20651d21e1
@ -18,6 +18,7 @@ type User struct {
|
|||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
PasswordHash string `json:"-"`
|
PasswordHash string `json:"-"`
|
||||||
|
OpenID string `json:"openId"`
|
||||||
UserSettingList []*UserSetting `json:"userSettingList"`
|
UserSettingList []*UserSetting `json:"userSettingList"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,6 +27,7 @@ type UserCreate struct {
|
|||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
PasswordHash string
|
PasswordHash string
|
||||||
|
OpenID string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (create UserCreate) Validate() error {
|
func (create UserCreate) Validate() error {
|
||||||
@ -53,6 +55,8 @@ type UserPatch struct {
|
|||||||
Name *string `json:"name"`
|
Name *string `json:"name"`
|
||||||
Password *string `json:"password"`
|
Password *string `json:"password"`
|
||||||
PasswordHash *string
|
PasswordHash *string
|
||||||
|
ResetOpenID *bool `json:"resetOpenId"`
|
||||||
|
OpenID *string
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserFind struct {
|
type UserFind struct {
|
||||||
@ -62,8 +66,9 @@ type UserFind struct {
|
|||||||
RowStatus *RowStatus `json:"rowStatus"`
|
RowStatus *RowStatus `json:"rowStatus"`
|
||||||
|
|
||||||
// Domain specific fields
|
// Domain specific fields
|
||||||
Email *string `json:"email"`
|
Email *string `json:"email"`
|
||||||
Name *string `json:"name"`
|
Name *string `json:"name"`
|
||||||
|
OpenID *string `json:"openId"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserDelete struct {
|
type UserDelete struct {
|
||||||
|
@ -64,6 +64,25 @@ func aclMiddleware(s *Server, next echo.HandlerFunc) echo.HandlerFunc {
|
|||||||
return next(c)
|
return next(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// If there is openId in query string and related user is found, then skip auth.
|
||||||
|
openID := c.QueryParam("openId")
|
||||||
|
if openID != "" {
|
||||||
|
userFind := &api.UserFind{
|
||||||
|
OpenID: &openID,
|
||||||
|
}
|
||||||
|
user, err := s.Store.FindUser(ctx, userFind)
|
||||||
|
if err != nil && common.ErrorCode(err) != common.NotFound {
|
||||||
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find user by open_id").SetInternal(err)
|
||||||
|
}
|
||||||
|
if user != nil {
|
||||||
|
// Stores userID into context.
|
||||||
|
c.Set(getUserIDContextKey(), user.ID)
|
||||||
|
return next(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
sess, _ := session.Get("session", c)
|
sess, _ := session.Get("session", c)
|
||||||
userIDValue := sess.Values[userIDContextKey]
|
userIDValue := sess.Values[userIDContextKey]
|
||||||
|
@ -61,6 +61,7 @@ func (s *Server) registerAuthRoutes(g *echo.Group) {
|
|||||||
Email: signup.Email,
|
Email: signup.Email,
|
||||||
Name: signup.Name,
|
Name: signup.Name,
|
||||||
Password: signup.Password,
|
Password: signup.Password,
|
||||||
|
OpenID: common.GenUUID(),
|
||||||
}
|
}
|
||||||
if err := userCreate.Validate(); err != nil {
|
if err := userCreate.Validate(); err != nil {
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Invalid user create format.").SetInternal(err)
|
return echo.NewHTTPError(http.StatusBadRequest, "Invalid user create format.").SetInternal(err)
|
||||||
|
@ -59,34 +59,6 @@ func (s *Server) registerUserRoutes(g *echo.Group) {
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
g.POST("/user/setting", func(c echo.Context) error {
|
|
||||||
ctx := c.Request().Context()
|
|
||||||
userID, ok := c.Get(getUserIDContextKey()).(int)
|
|
||||||
if !ok {
|
|
||||||
return echo.NewHTTPError(http.StatusUnauthorized, "Missing auth session")
|
|
||||||
}
|
|
||||||
|
|
||||||
userSettingUpsert := &api.UserSettingUpsert{}
|
|
||||||
if err := json.NewDecoder(c.Request().Body).Decode(userSettingUpsert); err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted post user setting upsert request").SetInternal(err)
|
|
||||||
}
|
|
||||||
if err := userSettingUpsert.Validate(); err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Invalid user setting format").SetInternal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
userSettingUpsert.UserID = userID
|
|
||||||
userSetting, err := s.Store.UpsertUserSetting(ctx, userSettingUpsert)
|
|
||||||
if err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to upsert user setting").SetInternal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8)
|
|
||||||
if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(userSetting)); err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode user setting response").SetInternal(err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
g.GET("/user/:id", func(c echo.Context) error {
|
g.GET("/user/:id", func(c echo.Context) error {
|
||||||
ctx := c.Request().Context()
|
ctx := c.Request().Context()
|
||||||
id, err := strconv.Atoi(c.Param("id"))
|
id, err := strconv.Atoi(c.Param("id"))
|
||||||
@ -151,6 +123,11 @@ func (s *Server) registerUserRoutes(g *echo.Group) {
|
|||||||
userPatch.PasswordHash = &passwordHashStr
|
userPatch.PasswordHash = &passwordHashStr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if userPatch.ResetOpenID != nil && *userPatch.ResetOpenID {
|
||||||
|
uuid := common.GenUUID()
|
||||||
|
userPatch.OpenID = &uuid
|
||||||
|
}
|
||||||
|
|
||||||
user, err := s.Store.PatchUser(ctx, userPatch)
|
user, err := s.Store.PatchUser(ctx, userPatch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to patch user").SetInternal(err)
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to patch user").SetInternal(err)
|
||||||
@ -163,6 +140,34 @@ func (s *Server) registerUserRoutes(g *echo.Group) {
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
|
g.POST("/user/setting", func(c echo.Context) error {
|
||||||
|
ctx := c.Request().Context()
|
||||||
|
userID, ok := c.Get(getUserIDContextKey()).(int)
|
||||||
|
if !ok {
|
||||||
|
return echo.NewHTTPError(http.StatusUnauthorized, "Missing auth session")
|
||||||
|
}
|
||||||
|
|
||||||
|
userSettingUpsert := &api.UserSettingUpsert{}
|
||||||
|
if err := json.NewDecoder(c.Request().Body).Decode(userSettingUpsert); err != nil {
|
||||||
|
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted post user setting upsert request").SetInternal(err)
|
||||||
|
}
|
||||||
|
if err := userSettingUpsert.Validate(); err != nil {
|
||||||
|
return echo.NewHTTPError(http.StatusBadRequest, "Invalid user setting format").SetInternal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
userSettingUpsert.UserID = userID
|
||||||
|
userSetting, err := s.Store.UpsertUserSetting(ctx, userSettingUpsert)
|
||||||
|
if err != nil {
|
||||||
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to upsert user setting").SetInternal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8)
|
||||||
|
if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(userSetting)); err != nil {
|
||||||
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode user setting response").SetInternal(err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
g.DELETE("/user/:id", func(c echo.Context) error {
|
g.DELETE("/user/:id", func(c echo.Context) error {
|
||||||
ctx := c.Request().Context()
|
ctx := c.Request().Context()
|
||||||
currentUserID, ok := c.Get(getUserIDContextKey()).(int)
|
currentUserID, ok := c.Get(getUserIDContextKey()).(int)
|
||||||
|
@ -55,7 +55,8 @@ CREATE TABLE user (
|
|||||||
row_status TEXT NOT NULL CHECK (row_status IN ('NORMAL', 'ARCHIVED')) DEFAULT 'NORMAL',
|
row_status TEXT NOT NULL CHECK (row_status IN ('NORMAL', 'ARCHIVED')) DEFAULT 'NORMAL',
|
||||||
email TEXT NOT NULL UNIQUE,
|
email TEXT NOT NULL UNIQUE,
|
||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
password_hash TEXT NOT NULL
|
password_hash TEXT NOT NULL,
|
||||||
|
open_id TEXT NOT NULL UNIQUE
|
||||||
);
|
);
|
||||||
|
|
||||||
INSERT INTO
|
INSERT INTO
|
||||||
@ -75,6 +76,12 @@ WHERE
|
|||||||
rowid = old.rowid;
|
rowid = old.rowid;
|
||||||
END;
|
END;
|
||||||
|
|
||||||
|
CREATE INDEX user_id_index ON user(id);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX user_email_index ON user(email);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX user_open_id_index ON user(open_id);
|
||||||
|
|
||||||
-- user_setting
|
-- user_setting
|
||||||
CREATE TABLE user_setting (
|
CREATE TABLE user_setting (
|
||||||
user_id INTEGER NOT NULL,
|
user_id INTEGER NOT NULL,
|
||||||
|
@ -3,7 +3,8 @@ INSERT INTO
|
|||||||
`id`,
|
`id`,
|
||||||
`email`,
|
`email`,
|
||||||
`name`,
|
`name`,
|
||||||
`password_hash`
|
`password_hash`,
|
||||||
|
`open_id`
|
||||||
)
|
)
|
||||||
VALUES
|
VALUES
|
||||||
(
|
(
|
||||||
@ -11,39 +12,6 @@ VALUES
|
|||||||
'demo@iamcorgi.com',
|
'demo@iamcorgi.com',
|
||||||
'Demo Host',
|
'Demo Host',
|
||||||
-- raw password: secret
|
-- raw password: secret
|
||||||
'$2a$14$ajq8Q7fbtFRQvXpdCq7Jcuy.Rx1h/L4J60Otx.gyNLbAYctGMJ9tK'
|
'$2a$14$ajq8Q7fbtFRQvXpdCq7Jcuy.Rx1h/L4J60Otx.gyNLbAYctGMJ9tK',
|
||||||
);
|
'demo_open_id'
|
||||||
|
|
||||||
INSERT INTO
|
|
||||||
user (
|
|
||||||
`id`,
|
|
||||||
`email`,
|
|
||||||
`name`,
|
|
||||||
`password_hash`
|
|
||||||
)
|
|
||||||
VALUES
|
|
||||||
(
|
|
||||||
102,
|
|
||||||
'jack@iamcorgi.com',
|
|
||||||
'Jack',
|
|
||||||
-- raw password: secret
|
|
||||||
'$2a$14$ajq8Q7fbtFRQvXpdCq7Jcuy.Rx1h/L4J60Otx.gyNLbAYctGMJ9tK'
|
|
||||||
);
|
|
||||||
|
|
||||||
INSERT INTO
|
|
||||||
user (
|
|
||||||
`id`,
|
|
||||||
`row_status`,
|
|
||||||
`email`,
|
|
||||||
`name`,
|
|
||||||
`password_hash`
|
|
||||||
)
|
|
||||||
VALUES
|
|
||||||
(
|
|
||||||
103,
|
|
||||||
'ARCHIVED',
|
|
||||||
'bob@iamcorgi.com',
|
|
||||||
'Bob',
|
|
||||||
-- raw password: secret
|
|
||||||
'$2a$14$ajq8Q7fbtFRQvXpdCq7Jcuy.Rx1h/L4J60Otx.gyNLbAYctGMJ9tK'
|
|
||||||
);
|
);
|
@ -24,6 +24,7 @@ type userRaw struct {
|
|||||||
Email string
|
Email string
|
||||||
Name string
|
Name string
|
||||||
PasswordHash string
|
PasswordHash string
|
||||||
|
OpenID string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (raw *userRaw) toUser() *api.User {
|
func (raw *userRaw) toUser() *api.User {
|
||||||
@ -37,6 +38,7 @@ func (raw *userRaw) toUser() *api.User {
|
|||||||
Email: raw.Email,
|
Email: raw.Email,
|
||||||
Name: raw.Name,
|
Name: raw.Name,
|
||||||
PasswordHash: raw.PasswordHash,
|
PasswordHash: raw.PasswordHash,
|
||||||
|
OpenID: raw.OpenID,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,24 +176,27 @@ func createUser(ctx context.Context, tx *sql.Tx, create *api.UserCreate) (*userR
|
|||||||
INSERT INTO user (
|
INSERT INTO user (
|
||||||
email,
|
email,
|
||||||
name,
|
name,
|
||||||
password_hash
|
password_hash,
|
||||||
|
open_id
|
||||||
)
|
)
|
||||||
VALUES (?, ?, ?)
|
VALUES (?, ?, ?, ?)
|
||||||
RETURNING id, email, name, password_hash, created_ts, updated_ts, row_status
|
RETURNING id, created_ts, updated_ts, row_status, email, name, password_hash, open_id
|
||||||
`
|
`
|
||||||
var userRaw userRaw
|
var userRaw userRaw
|
||||||
if err := tx.QueryRowContext(ctx, query,
|
if err := tx.QueryRowContext(ctx, query,
|
||||||
create.Email,
|
create.Email,
|
||||||
create.Name,
|
create.Name,
|
||||||
create.PasswordHash,
|
create.PasswordHash,
|
||||||
|
create.OpenID,
|
||||||
).Scan(
|
).Scan(
|
||||||
&userRaw.ID,
|
&userRaw.ID,
|
||||||
&userRaw.Email,
|
|
||||||
&userRaw.Name,
|
|
||||||
&userRaw.PasswordHash,
|
|
||||||
&userRaw.CreatedTs,
|
&userRaw.CreatedTs,
|
||||||
&userRaw.UpdatedTs,
|
&userRaw.UpdatedTs,
|
||||||
&userRaw.RowStatus,
|
&userRaw.RowStatus,
|
||||||
|
&userRaw.Email,
|
||||||
|
&userRaw.Name,
|
||||||
|
&userRaw.PasswordHash,
|
||||||
|
&userRaw.OpenID,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, FormatError(err)
|
return nil, FormatError(err)
|
||||||
}
|
}
|
||||||
@ -214,6 +219,9 @@ func patchUser(ctx context.Context, tx *sql.Tx, patch *api.UserPatch) (*userRaw,
|
|||||||
if v := patch.PasswordHash; v != nil {
|
if v := patch.PasswordHash; v != nil {
|
||||||
set, args = append(set, "password_hash = ?"), append(args, *v)
|
set, args = append(set, "password_hash = ?"), append(args, *v)
|
||||||
}
|
}
|
||||||
|
if v := patch.OpenID; v != nil {
|
||||||
|
set, args = append(set, "open_id = ?"), append(args, *v)
|
||||||
|
}
|
||||||
|
|
||||||
args = append(args, patch.ID)
|
args = append(args, patch.ID)
|
||||||
|
|
||||||
@ -221,7 +229,7 @@ func patchUser(ctx context.Context, tx *sql.Tx, patch *api.UserPatch) (*userRaw,
|
|||||||
UPDATE user
|
UPDATE user
|
||||||
SET ` + strings.Join(set, ", ") + `
|
SET ` + strings.Join(set, ", ") + `
|
||||||
WHERE id = ?
|
WHERE id = ?
|
||||||
RETURNING id, created_ts, updated_ts, row_status, email, name, password_hash
|
RETURNING id, created_ts, updated_ts, row_status, email, name, password_hash, open_id
|
||||||
`
|
`
|
||||||
row, err := tx.QueryContext(ctx, query, args...)
|
row, err := tx.QueryContext(ctx, query, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -239,6 +247,7 @@ func patchUser(ctx context.Context, tx *sql.Tx, patch *api.UserPatch) (*userRaw,
|
|||||||
&userRaw.Email,
|
&userRaw.Email,
|
||||||
&userRaw.Name,
|
&userRaw.Name,
|
||||||
&userRaw.PasswordHash,
|
&userRaw.PasswordHash,
|
||||||
|
&userRaw.OpenID,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, FormatError(err)
|
return nil, FormatError(err)
|
||||||
}
|
}
|
||||||
@ -265,6 +274,9 @@ func findUserList(ctx context.Context, tx *sql.Tx, find *api.UserFind) ([]*userR
|
|||||||
if v := find.Name; v != nil {
|
if v := find.Name; v != nil {
|
||||||
where, args = append(where, "name = ?"), append(args, *v)
|
where, args = append(where, "name = ?"), append(args, *v)
|
||||||
}
|
}
|
||||||
|
if v := find.OpenID; v != nil {
|
||||||
|
where, args = append(where, "open_id = ?"), append(args, *v)
|
||||||
|
}
|
||||||
|
|
||||||
query := `
|
query := `
|
||||||
SELECT
|
SELECT
|
||||||
@ -274,7 +286,8 @@ func findUserList(ctx context.Context, tx *sql.Tx, find *api.UserFind) ([]*userR
|
|||||||
row_status,
|
row_status,
|
||||||
email,
|
email,
|
||||||
name,
|
name,
|
||||||
password_hash
|
password_hash,
|
||||||
|
open_id
|
||||||
FROM user
|
FROM user
|
||||||
WHERE ` + strings.Join(where, " AND ") + `
|
WHERE ` + strings.Join(where, " AND ") + `
|
||||||
ORDER BY updated_ts DESC, created_ts DESC, row_status DESC
|
ORDER BY updated_ts DESC, created_ts DESC, row_status DESC
|
||||||
@ -296,6 +309,7 @@ func findUserList(ctx context.Context, tx *sql.Tx, find *api.UserFind) ([]*userR
|
|||||||
&userRaw.Email,
|
&userRaw.Email,
|
||||||
&userRaw.Name,
|
&userRaw.Name,
|
||||||
&userRaw.PasswordHash,
|
&userRaw.PasswordHash,
|
||||||
|
&userRaw.OpenID,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, FormatError(err)
|
return nil, FormatError(err)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user