chore: rename user role (#108)

* chore: rename user role to `host`

* chore: related frontend changes

* chore: fix migration file

* chore: use tricky sql
pull/113/head
boojack 3 years ago committed by GitHub
parent 6f32643d7c
commit bdc9632b5b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -3,6 +3,6 @@ package api
import "github.com/usememos/memos/server/profile"
type SystemStatus struct {
Owner *User `json:"owner"`
Host *User `json:"host"`
Profile *profile.Profile `json:"profile"`
}

@ -4,16 +4,16 @@ package api
type Role string
const (
// Owner is the OWNER role.
Owner Role = "OWNER"
// Host is the HOST role.
Host Role = "HOST"
// NormalUser is the USER role.
NormalUser Role = "USER"
)
func (e Role) String() string {
switch e {
case Owner:
return "OWNER"
case Host:
return "HOST"
case NormalUser:
return "USER"
}

@ -60,17 +60,17 @@ func (s *Server) registerAuthRoutes(g *echo.Group) {
})
g.POST("/auth/signup", func(c echo.Context) error {
// Don't allow to signup by this api if site owner existed.
ownerUserType := api.Owner
ownerUserFind := api.UserFind{
Role: &ownerUserType,
// Don't allow to signup by this api if site host existed.
hostUserType := api.Host
hostUserFind := api.UserFind{
Role: &hostUserType,
}
ownerUser, err := s.Store.FindUser(&ownerUserFind)
hostUser, err := s.Store.FindUser(&hostUserFind)
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find owner user").SetInternal(err)
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find host user").SetInternal(err)
}
if ownerUser != nil {
return echo.NewHTTPError(http.StatusUnauthorized, "Site Owner existed, please contact the site owner to signin account firstly.").SetInternal(err)
if hostUser != nil {
return echo.NewHTTPError(http.StatusUnauthorized, "Site Host existed, please contact the site host to signin account firstly.").SetInternal(err)
}
signup := &api.Signup{}

@ -21,22 +21,22 @@ func (s *Server) registerSystemRoutes(g *echo.Group) {
})
g.GET("/status", func(c echo.Context) error {
ownerUserType := api.Owner
ownerUserFind := api.UserFind{
Role: &ownerUserType,
hostUserType := api.Host
hostUserFind := api.UserFind{
Role: &hostUserType,
}
ownerUser, err := s.Store.FindUser(&ownerUserFind)
hostUser, err := s.Store.FindUser(&hostUserFind)
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find owner user").SetInternal(err)
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find host user").SetInternal(err)
}
if ownerUser != nil {
if hostUser != nil {
// data desensitize
ownerUser.OpenID = ""
hostUser.OpenID = ""
}
systemStatus := api.SystemStatus{
Owner: ownerUser,
Host: hostUser,
Profile: s.Profile,
}

@ -143,7 +143,7 @@ func (s *Server) registerUserRoutes(g *echo.Group) {
}
if currentUser == nil {
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Current session user not found with ID: %d", currentUserID)).SetInternal(err)
} else if currentUser.Role != api.Owner {
} else if currentUser.Role != api.Host {
return echo.NewHTTPError(http.StatusForbidden, "Access forbidden for current session user").SetInternal(err)
}

@ -0,0 +1,56 @@
-- change user role field from "OWNER"/"USER" to "HOST"/"USER".
PRAGMA foreign_keys = off;
BEGIN TRANSACTION;
DROP TABLE IF EXISTS _user_old;
ALTER TABLE
user RENAME TO _user_old;
CREATE TABLE user (
id INTEGER PRIMARY KEY AUTOINCREMENT,
created_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')),
updated_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')),
row_status TEXT NOT NULL CHECK (row_status IN ('NORMAL', 'ARCHIVED')) DEFAULT 'NORMAL',
email TEXT NOT NULL UNIQUE,
role TEXT NOT NULL CHECK (role IN ('HOST', 'USER')) DEFAULT 'USER',
name TEXT NOT NULL,
password_hash TEXT NOT NULL,
open_id TEXT NOT NULL UNIQUE
);
INSERT INTO user (
id, created_ts, updated_ts, row_status,
email, name, password_hash, open_id
)
SELECT
id,
created_ts,
updated_ts,
row_status,
email,
name,
password_hash,
open_id
FROM
_user_old;
UPDATE
user
SET
role = 'HOST'
WHERE
id IN (
SELECT
id
FROM
_user_old
WHERE
role = 'OWNER'
);
DROP TABLE IF EXISTS _user_old;
COMMIT;
PRAGMA foreign_keys = on;

@ -13,7 +13,7 @@ CREATE TABLE user (
-- allowed row status are 'NORMAL', 'ARCHIVED'.
row_status TEXT NOT NULL CHECK (row_status IN ('NORMAL', 'ARCHIVED')) DEFAULT 'NORMAL',
email TEXT NOT NULL UNIQUE,
role TEXT NOT NULL CHECK (role IN ('OWNER', 'USER')) DEFAULT 'USER',
role TEXT NOT NULL CHECK (role IN ('HOST', 'USER')) DEFAULT 'USER',
name TEXT NOT NULL,
password_hash TEXT NOT NULL,
open_id TEXT NOT NULL UNIQUE

@ -11,8 +11,8 @@ VALUES
(
101,
'demo@usememos.com',
'OWNER',
'Demo Owner',
'HOST',
'Demo Host',
'demo_open_id',
-- raw password: secret
'$2a$14$ajq8Q7fbtFRQvXpdCq7Jcuy.Rx1h/L4J60Otx.gyNLbAYctGMJ9tK'

@ -106,7 +106,7 @@ func createUser(db *sql.DB, create *api.UserCreate) (*userRaw, error) {
open_id
)
VALUES (?, ?, ?, ?, ?)
RETURNING id, email, role, name, password_hash, open_id, created_ts, updated_ts
RETURNING id, email, role, name, password_hash, open_id, created_ts, updated_ts, row_status
`,
create.Email,
create.Role,
@ -130,6 +130,7 @@ func createUser(db *sql.DB, create *api.UserCreate) (*userRaw, error) {
&userRaw.OpenID,
&userRaw.CreatedTs,
&userRaw.UpdatedTs,
&userRaw.RowStatus,
); err != nil {
return nil, FormatError(err)
}
@ -162,7 +163,7 @@ func patchUser(db *sql.DB, patch *api.UserPatch) (*userRaw, error) {
UPDATE user
SET `+strings.Join(set, ", ")+`
WHERE id = ?
RETURNING id, email, role, name, password_hash, open_id, created_ts, updated_ts
RETURNING id, email, role, name, password_hash, open_id, created_ts, updated_ts, row_status
`, args...)
if err != nil {
return nil, FormatError(err)
@ -180,6 +181,7 @@ func patchUser(db *sql.DB, patch *api.UserPatch) (*userRaw, error) {
&userRaw.OpenID,
&userRaw.CreatedTs,
&userRaw.UpdatedTs,
&userRaw.RowStatus,
); err != nil {
return nil, FormatError(err)
}
@ -218,7 +220,8 @@ func findUserList(db *sql.DB, find *api.UserFind) ([]*userRaw, error) {
password_hash,
open_id,
created_ts,
updated_ts
updated_ts,
row_status
FROM user
WHERE `+strings.Join(where, " AND ")+`
ORDER BY created_ts DESC`,
@ -241,6 +244,7 @@ func findUserList(db *sql.DB, find *api.UserFind) ([]*userRaw, error) {
&userRaw.OpenID,
&userRaw.CreatedTs,
&userRaw.UpdatedTs,
&userRaw.RowStatus,
); err != nil {
fmt.Println(err)
return nil, FormatError(err)

@ -48,7 +48,7 @@ const SettingDialog: React.FC<Props> = (props: Props) => {
<span className="icon-text">🏟</span> Preferences
</span>
</div>
{user?.role === "OWNER" ? (
{user?.role === "HOST" ? (
<>
<span className="section-title">Admin</span>
<div className="section-items-container">

@ -28,7 +28,7 @@ const UserBanner: React.FC<Props> = () => {
if (locationService.getState().pathname === "/") {
api.getSystemStatus().then(({ data }) => {
const { data: status } = data;
setUsername(status.owner.name);
setUsername(status.host.name);
});
} else {
const currentUserId = userService.getCurrentUserId();
@ -51,7 +51,7 @@ const UserBanner: React.FC<Props> = () => {
<div className="user-banner-container">
<div className="username-container" onClick={handleUsernameClick}>
<span className="username-text">{username}</span>
{user?.role === "OWNER" ? <span className="tag">MOD</span> : null}
{user?.role === "HOST" ? <span className="tag">MOD</span> : null}
</div>
<span className="action-btn menu-popup-btn" onClick={handlePopupBtnClick}>
<img src="/icons/more.svg" className="icon-img" />

@ -69,7 +69,7 @@
> .tip-text {
@apply w-auto inline-block float-right text-sm mt-4 text-gray-500 text-right whitespace-pre-wrap;
&.owner-tip {
&.host-tip {
@apply bg-blue-500 text-white px-2 py-1 rounded;
}
}

@ -17,7 +17,7 @@ const validateConfig: ValidatorConfig = {
const Signin: React.FC<Props> = () => {
const pageLoadingState = useLoading(true);
const [siteOwner, setSiteOwner] = useState<User>();
const [siteHost, setSiteHost] = useState<User>();
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const actionBtnLoadingState = useLoading(false);
@ -25,7 +25,7 @@ const Signin: React.FC<Props> = () => {
useEffect(() => {
api.getSystemStatus().then(({ data }) => {
const { data: status } = data;
setSiteOwner(status.owner);
setSiteHost(status.host);
if (status.profile.mode === "dev") {
setEmail("demo@usememos.com");
setPassword("secret");
@ -77,7 +77,7 @@ const Signin: React.FC<Props> = () => {
actionBtnLoadingState.setFinish();
};
const handleSignUpAsOwnerBtnsClick = async () => {
const handleSignUpAsHostBtnsClick = async () => {
if (actionBtnLoadingState.isLoading) {
return;
}
@ -96,7 +96,7 @@ const Signin: React.FC<Props> = () => {
try {
actionBtnLoadingState.setLoading();
await api.signup(email, password, "OWNER");
await api.signup(email, password, "HOST");
const user = await userService.doSignIn();
if (user) {
locationService.replaceHistory("/");
@ -132,7 +132,7 @@ const Signin: React.FC<Props> = () => {
</div>
</div>
<div className="action-btns-container">
{siteOwner || pageLoadingState.isLoading ? (
{siteHost || pageLoadingState.isLoading ? (
<button
className={`btn signin-btn ${actionBtnLoadingState.isLoading ? "requesting" : ""}`}
onClick={() => handleSigninBtnsClick()}
@ -142,16 +142,16 @@ const Signin: React.FC<Props> = () => {
) : (
<button
className={`btn signin-btn ${actionBtnLoadingState.isLoading ? "requesting" : ""}`}
onClick={() => handleSignUpAsOwnerBtnsClick()}
onClick={() => handleSignUpAsHostBtnsClick()}
>
Sign up as Owner
Sign up as Host
</button>
)}
</div>
<p className={`tip-text ${siteOwner || pageLoadingState.isLoading ? "" : "owner-tip"}`}>
{siteOwner || pageLoadingState.isLoading
? "If you don't have an account, please\ncontact the site owner."
: "You are registering as the Site Owner."}
<p className={`tip-text ${siteHost || pageLoadingState.isLoading ? "" : "host-tip"}`}>
{siteHost || pageLoadingState.isLoading
? "If you don't have an account, please\ncontact the site host."
: "You are registering as the Site Host."}
</p>
</div>
</div>

@ -4,6 +4,6 @@ interface Profile {
}
interface SystemStatus {
owner: User;
host: User;
profile: Profile;
}

@ -1,5 +1,5 @@
type UserId = number;
type UserRole = "OWNER" | "USER";
type UserRole = "HOST" | "USER";
interface User {
id: UserId;

Loading…
Cancel
Save