refactor: migrate HOST roles to ADMIN

- Updated the isSuperUser function to only check for ADMIN role.
- Added SQL migration scripts for MySQL, PostgreSQL, and SQLite to change user roles from HOST to ADMIN.
- Created a new SQLite migration to alter the user table structure and ensure data integrity during the migration process.
This commit is contained in:
Johnny 2026-01-20 23:38:30 +08:00
parent 47ebb04dc3
commit 0f3c9a467d
26 changed files with 97 additions and 109 deletions

View File

@ -38,7 +38,7 @@ var (
if err := instanceProfile.Validate(); err != nil {
slog.Error("failed to validate profile", "error", err)
os.Exit(1)
return
}
ctx, cancel := context.WithCancel(context.Background())
@ -46,21 +46,21 @@ var (
if err != nil {
cancel()
slog.Error("failed to create db driver", "error", err)
os.Exit(1)
return
}
storeInstance := store.New(dbDriver, instanceProfile)
if err := storeInstance.Migrate(ctx); err != nil {
cancel()
slog.Error("failed to migrate", "error", err)
os.Exit(1)
return
}
s, err := server.NewServer(ctx, instanceProfile, storeInstance)
if err != nil {
cancel()
slog.Error("failed to create server", "error", err)
os.Exit(1)
return
}
c := make(chan os.Signal, 1)
@ -73,7 +73,7 @@ var (
if err != http.ErrServerClosed {
slog.Error("failed to start server", "error", err)
cancel()
os.Exit(1)
return
}
}

View File

@ -203,13 +203,10 @@ message User {
// User role enumeration.
enum Role {
// Unspecified role.
ROLE_UNSPECIFIED = 0;
// Host role with full system access.
HOST = 1;
// Admin role with administrative privileges.
// Admin role with system access.
ADMIN = 2;
// Regular user role.
// User role with limited access.
USER = 3;
}
}

View File

@ -29,13 +29,10 @@ const (
type User_Role int32
const (
// Unspecified role.
User_ROLE_UNSPECIFIED User_Role = 0
// Host role with full system access.
User_HOST User_Role = 1
// Admin role with administrative privileges.
// Admin role with system access.
User_ADMIN User_Role = 2
// Regular user role.
// User role with limited access.
User_USER User_Role = 3
)
@ -43,13 +40,11 @@ const (
var (
User_Role_name = map[int32]string{
0: "ROLE_UNSPECIFIED",
1: "HOST",
2: "ADMIN",
3: "USER",
}
User_Role_value = map[string]int32{
"ROLE_UNSPECIFIED": 0,
"HOST": 1,
"ADMIN": 2,
"USER": 3,
}
@ -2509,7 +2504,7 @@ var File_api_v1_user_service_proto protoreflect.FileDescriptor
const file_api_v1_user_service_proto_rawDesc = "" +
"\n" +
"\x19api/v1/user_service.proto\x12\fmemos.api.v1\x1a\x13api/v1/common.proto\x1a\x1cgoogle/api/annotations.proto\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xcb\x04\n" +
"\x19api/v1/user_service.proto\x12\fmemos.api.v1\x1a\x13api/v1/common.proto\x1a\x1cgoogle/api/annotations.proto\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xc1\x04\n" +
"\x04User\x12\x17\n" +
"\x04name\x18\x01 \x01(\tB\x03\xe0A\bR\x04name\x120\n" +
"\x04role\x18\x02 \x01(\x0e2\x17.memos.api.v1.User.RoleB\x03\xe0A\x02R\x04role\x12\x1f\n" +
@ -2525,10 +2520,9 @@ const file_api_v1_user_service_proto_rawDesc = "" +
" \x01(\v2\x1a.google.protobuf.TimestampB\x03\xe0A\x03R\n" +
"createTime\x12@\n" +
"\vupdate_time\x18\v \x01(\v2\x1a.google.protobuf.TimestampB\x03\xe0A\x03R\n" +
"updateTime\";\n" +
"updateTime\"1\n" +
"\x04Role\x12\x14\n" +
"\x10ROLE_UNSPECIFIED\x10\x00\x12\b\n" +
"\x04HOST\x10\x01\x12\t\n" +
"\x10ROLE_UNSPECIFIED\x10\x00\x12\t\n" +
"\x05ADMIN\x10\x02\x12\b\n" +
"\x04USER\x10\x03:7\xeaA4\n" +
"\x11memos.api.v1/User\x12\fusers/{user}\x1a\x04name*\x05users2\x04user\"\x9d\x01\n" +

View File

@ -2859,7 +2859,6 @@ components:
role:
enum:
- ROLE_UNSPECIFIED
- HOST
- ADMIN
- USER
type: string

View File

@ -74,7 +74,7 @@ func TestParseAccessTokenV2(t *testing.T) {
})
t.Run("parses token with different roles", func(t *testing.T) {
roles := []string{"USER", "ADMIN", "HOST"}
roles := []string{"USER", "ADMIN"}
for _, role := range roles {
token, _, err := GenerateAccessTokenV2(1, "testuser", role, "ACTIVE", secret)
require.NoError(t, err)

View File

@ -64,5 +64,5 @@ func unmarshalPageToken(s string, pageToken *v1pb.PageToken) error {
}
func isSuperUser(user *store.User) bool {
return user.Role == store.RoleAdmin || user.Role == store.RoleHost
return user.Role == store.RoleAdmin
}

View File

@ -21,7 +21,7 @@ func (s *APIV1Service) CreateIdentityProvider(ctx context.Context, request *v1pb
if currentUser == nil {
return nil, status.Errorf(codes.Unauthenticated, "user not authenticated")
}
if currentUser.Role != store.RoleHost {
if currentUser.Role != store.RoleAdmin {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
@ -90,7 +90,7 @@ func (s *APIV1Service) UpdateIdentityProvider(ctx context.Context, request *v1pb
if currentUser == nil {
return nil, status.Errorf(codes.Unauthenticated, "user not authenticated")
}
if currentUser.Role != store.RoleHost {
if currentUser.Role != store.RoleAdmin {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
@ -134,7 +134,7 @@ func (s *APIV1Service) DeleteIdentityProvider(ctx context.Context, request *v1pb
if currentUser == nil {
return nil, status.Errorf(codes.Unauthenticated, "user not authenticated")
}
if currentUser.Role != store.RoleHost {
if currentUser.Role != store.RoleAdmin {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
@ -228,7 +228,7 @@ func convertIdentityProviderConfigToStore(identityProviderType v1pb.IdentityProv
}
func redactIdentityProviderResponse(identityProvider *v1pb.IdentityProvider, userRole store.Role) *v1pb.IdentityProvider {
if userRole != store.RoleHost {
if userRole != store.RoleAdmin {
if identityProvider.Type == v1pb.IdentityProvider_OAUTH2 {
identityProvider.Config.GetOauth2Config().ClientSecret = ""
}

View File

@ -64,7 +64,7 @@ func (s *APIV1Service) GetInstanceSetting(ctx context.Context, request *v1pb.Get
return nil, status.Errorf(codes.NotFound, "instance setting not found")
}
// For storage setting, only host can get it.
// For storage setting, only admin can get it.
if instanceSetting.Key == storepb.InstanceSettingKey_STORAGE {
user, err := s.fetchCurrentUser(ctx)
if err != nil {
@ -73,7 +73,7 @@ func (s *APIV1Service) GetInstanceSetting(ctx context.Context, request *v1pb.Get
if user == nil {
return nil, status.Errorf(codes.Unauthenticated, "user not authenticated")
}
if user.Role != store.RoleHost {
if user.Role != store.RoleAdmin {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
}
@ -89,7 +89,7 @@ func (s *APIV1Service) UpdateInstanceSetting(ctx context.Context, request *v1pb.
if user == nil {
return nil, status.Errorf(codes.Unauthenticated, "user not authenticated")
}
if user.Role != store.RoleHost {
if user.Role != store.RoleAdmin {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
@ -277,9 +277,9 @@ func (s *APIV1Service) GetInstanceOwner(ctx context.Context) (*v1pb.User, error)
return ownerCache, nil
}
hostUserType := store.RoleHost
adminUserType := store.RoleAdmin
user, err := s.Store.GetUser(ctx, &store.FindUser{
Role: &hostUserType,
Role: &adminUserType,
})
if err != nil {
return nil, errors.Wrapf(err, "failed to find owner")

View File

@ -28,7 +28,7 @@ func TestGetInstanceProfile(t *testing.T) {
// Verify the response contains expected data
require.Equal(t, "test-1.0.0", resp.Version)
require.Equal(t, "dev", resp.Mode)
require.True(t, resp.Demo)
require.Equal(t, "http://localhost:8080", resp.InstanceUrl)
// Owner should be empty since no users are created
@ -55,7 +55,7 @@ func TestGetInstanceProfile(t *testing.T) {
// Verify the response contains expected data including owner
require.Equal(t, "test-1.0.0", resp.Version)
require.Equal(t, "dev", resp.Mode)
require.True(t, resp.Demo)
require.Equal(t, "http://localhost:8080", resp.InstanceUrl)
// User name should be "users/{id}" format where id is the user's ID
@ -102,7 +102,7 @@ func TestGetInstanceProfile_Concurrency(t *testing.T) {
case resp := <-results:
require.NotNil(t, resp)
require.Equal(t, "test-1.0.0", resp.Version)
require.Equal(t, "dev", resp.Mode)
require.True(t, resp.Demo)
require.Equal(t, "http://localhost:8080", resp.InstanceUrl)
require.Equal(t, expectedOwnerName, resp.Owner)
}

View File

@ -29,7 +29,7 @@ func NewTestService(t *testing.T) *TestService {
// Create a test profile
testProfile := &profile.Profile{
Mode: "dev",
Demo: true,
Version: "test-1.0.0",
InstanceURL: "http://localhost:8080",
Driver: "sqlite",
@ -62,11 +62,11 @@ func (ts *TestService) Cleanup() {
// Note: Owner cache is package-level in parent package, cannot clear from test package
}
// CreateHostUser creates a host user for testing.
// CreateHostUser creates an admin user for testing.
func (ts *TestService) CreateHostUser(ctx context.Context, username string) (*store.User, error) {
return ts.Store.CreateUser(ctx, &store.User{
Username: username,
Role: store.RoleHost,
Role: store.RoleAdmin,
Email: username + "@example.com",
})
}

View File

@ -37,7 +37,7 @@ func (s *APIV1Service) ListUsers(ctx context.Context, request *v1pb.ListUsersReq
if currentUser == nil {
return nil, status.Errorf(codes.Unauthenticated, "user not authenticated")
}
if currentUser.Role != store.RoleHost && currentUser.Role != store.RoleAdmin {
if currentUser.Role != store.RoleAdmin {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
@ -132,17 +132,17 @@ func (s *APIV1Service) CreateUser(ctx context.Context, request *v1pb.CreateUserR
// Determine the role to assign
var roleToAssign store.Role
if isFirstUser {
// First-time setup: create the first user as HOST (no authentication required)
roleToAssign = store.RoleHost
} else if currentUser != nil && currentUser.Role == store.RoleHost {
// Authenticated HOST user can create users with any role specified in request
// First-time setup: create the first user as ADMIN (no authentication required)
roleToAssign = store.RoleAdmin
} else if currentUser != nil && currentUser.Role == store.RoleAdmin {
// Authenticated ADMIN user can create users with any role specified in request
if request.User.Role != v1pb.User_ROLE_UNSPECIFIED {
roleToAssign = convertUserRoleToStore(request.User.Role)
} else {
roleToAssign = store.RoleUser
}
} else {
// Unauthenticated or non-HOST users can only create normal users
// Unauthenticated or non-ADMIN users can only create normal users
roleToAssign = store.RoleUser
}
@ -197,7 +197,7 @@ func (s *APIV1Service) UpdateUser(ctx context.Context, request *v1pb.UpdateUserR
}
// Check permission.
// Only allow admin or self to update user.
if currentUser.ID != userID && currentUser.Role != store.RoleAdmin && currentUser.Role != store.RoleHost {
if currentUser.ID != userID && currentUser.Role != store.RoleAdmin {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
@ -264,7 +264,7 @@ func (s *APIV1Service) UpdateUser(ctx context.Context, request *v1pb.UpdateUserR
update.Description = &request.User.Description
case "role":
// Only allow admin to update role.
if currentUser.Role != store.RoleAdmin && currentUser.Role != store.RoleHost {
if currentUser.Role != store.RoleAdmin {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
role := convertUserRoleToStore(request.User.Role)
@ -301,7 +301,7 @@ func (s *APIV1Service) DeleteUser(ctx context.Context, request *v1pb.DeleteUserR
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get user: %v", err)
}
if currentUser.ID != userID && currentUser.Role != store.RoleAdmin && currentUser.Role != store.RoleHost {
if currentUser.ID != userID && currentUser.Role != store.RoleAdmin {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
@ -542,7 +542,7 @@ func (s *APIV1Service) ListPersonalAccessTokens(ctx context.Context, request *v1
claims := auth.GetUserClaims(ctx)
if claims == nil || claims.UserID != userID {
currentUser, _ := s.fetchCurrentUser(ctx)
if currentUser == nil || (currentUser.ID != userID && currentUser.Role != store.RoleHost && currentUser.Role != store.RoleAdmin) {
if currentUser == nil || (currentUser.ID != userID && currentUser.Role != store.RoleAdmin) {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
}
@ -689,7 +689,7 @@ func (s *APIV1Service) ListUserWebhooks(ctx context.Context, request *v1pb.ListU
if currentUser == nil {
return nil, status.Errorf(codes.Unauthenticated, "user not authenticated")
}
if currentUser.ID != userID && currentUser.Role != store.RoleHost && currentUser.Role != store.RoleAdmin {
if currentUser.ID != userID && currentUser.Role != store.RoleAdmin {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
@ -721,7 +721,7 @@ func (s *APIV1Service) CreateUserWebhook(ctx context.Context, request *v1pb.Crea
if currentUser == nil {
return nil, status.Errorf(codes.Unauthenticated, "user not authenticated")
}
if currentUser.ID != userID && currentUser.Role != store.RoleHost && currentUser.Role != store.RoleAdmin {
if currentUser.ID != userID && currentUser.Role != store.RoleAdmin {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
@ -761,7 +761,7 @@ func (s *APIV1Service) UpdateUserWebhook(ctx context.Context, request *v1pb.Upda
if currentUser == nil {
return nil, status.Errorf(codes.Unauthenticated, "user not authenticated")
}
if currentUser.ID != userID && currentUser.Role != store.RoleHost && currentUser.Role != store.RoleAdmin {
if currentUser.ID != userID && currentUser.Role != store.RoleAdmin {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
@ -833,7 +833,7 @@ func (s *APIV1Service) DeleteUserWebhook(ctx context.Context, request *v1pb.Dele
if currentUser == nil {
return nil, status.Errorf(codes.Unauthenticated, "user not authenticated")
}
if currentUser.ID != userID && currentUser.Role != store.RoleHost && currentUser.Role != store.RoleAdmin {
if currentUser.ID != userID && currentUser.Role != store.RoleAdmin {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
@ -928,8 +928,6 @@ func convertUserFromStore(user *store.User) *v1pb.User {
func convertUserRoleFromStore(role store.Role) v1pb.User_Role {
switch role {
case store.RoleHost:
return v1pb.User_HOST
case store.RoleAdmin:
return v1pb.User_ADMIN
case store.RoleUser:
@ -941,8 +939,6 @@ func convertUserRoleFromStore(role store.Role) v1pb.User_Role {
func convertUserRoleToStore(role v1pb.User_Role) store.Role {
switch role {
case v1pb.User_HOST:
return store.RoleHost
case v1pb.User_ADMIN:
return store.RoleAdmin
default:

View File

@ -0,0 +1 @@
UPDATE `user` SET `role` = 'ADMIN' WHERE `role` = 'HOST';

View File

@ -0,0 +1 @@
UPDATE "user" SET role = 'ADMIN' WHERE role = 'HOST';

View File

@ -0,0 +1,24 @@
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',
username TEXT NOT NULL UNIQUE,
role TEXT NOT NULL DEFAULT 'USER',
email TEXT NOT NULL DEFAULT '',
nickname TEXT NOT NULL DEFAULT '',
password_hash TEXT NOT NULL,
avatar_url TEXT NOT NULL DEFAULT '',
description TEXT NOT NULL DEFAULT ''
);
INSERT INTO user (
id, created_ts, updated_ts, row_status, username, role, email, nickname, password_hash, avatar_url, description
)
SELECT
id, created_ts, updated_ts, row_status, username, role, email, nickname, password_hash, avatar_url, description
FROM user_old;
DROP TABLE user_old;

View File

@ -0,0 +1 @@
UPDATE user SET role = 'ADMIN' WHERE role = 'HOST';

View File

@ -13,7 +13,7 @@ CREATE TABLE user (
updated_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')),
row_status TEXT NOT NULL CHECK (row_status IN ('NORMAL', 'ARCHIVED')) DEFAULT 'NORMAL',
username TEXT NOT NULL UNIQUE,
role TEXT NOT NULL CHECK (role IN ('HOST', 'ADMIN', 'USER')) DEFAULT 'USER',
role TEXT NOT NULL DEFAULT 'USER',
email TEXT NOT NULL DEFAULT '',
nickname TEXT NOT NULL DEFAULT '',
password_hash TEXT NOT NULL,

View File

@ -244,16 +244,16 @@ func (s *Store) preMigrate(ctx context.Context) error {
return errors.Wrap(err, "failed to get current schema version")
}
slog.Info("database initialized successfully", slog.String("schemaVersion", schemaVersion))
if err := s.updateCurrentSchemaVersion(ctx, schemaVersion); err != nil {
return errors.Wrap(err, "failed to update current schema version")
}
}
if err := s.checkMinimumUpgradeVersion(ctx); err != nil {
return err // Error message is already descriptive, don't wrap it
}
return nil
if err := s.updateCurrentSchemaVersion(ctx, schemaVersion); err != nil {
return errors.Wrap(err, "failed to update current schema version")
}
}
if err := s.checkMinimumUpgradeVersion(ctx); err != nil {
return err // Error message is already descriptive, don't wrap it
}
return nil
}
func (s *Store) getMigrationBasePath() string {
return fmt.Sprintf("migration/%s/", s.profile.Driver)
}

View File

@ -10,7 +10,7 @@ The demo data includes **6 carefully selected memos** that showcase the key feat
- **Username**: `demo`
- **Password**: `secret` (default password)
- **Role**: HOST
- **Role**: ADMIN
- **Nickname**: Demo User
## Demo Memos (6 total)
@ -198,7 +198,7 @@ Login with:
- All memos are set to PUBLIC visibility
- **Two memos are pinned**: Welcome (#1) and Sponsor (#6)
- User has HOST role to showcase all features
- User has ADMIN role to showcase all features
- Reactions are distributed across memos
- One memo relation demonstrates linking
- Content is optimized for the compact markdown styles

View File

@ -1,5 +1,5 @@
-- Demo User
INSERT INTO user (id,username,role,nickname,password_hash) VALUES(1,'demo','HOST','Demo User','$2a$10$c.slEVgf5b/3BnAWlLb/vOu7VVSOKJ4ljwMe9xzlx9IhKnvAsJYM6');
INSERT INTO user (id,username,role,nickname,password_hash) VALUES(1,'demo','ADMIN','Demo User','$2a$10$c.slEVgf5b/3BnAWlLb/vOu7VVSOKJ4ljwMe9xzlx9IhKnvAsJYM6');
-- Welcome Memo (Pinned)
INSERT INTO memo (id,uid,creator_id,content,visibility,pinned,payload) VALUES(1,'welcome2memos001',1,replace('# Welcome to Memos!\\n\\nA privacy-first, lightweight note-taking service. Easily capture and share your great thoughts.\\n\\n## Key Features\\n\\n- **Privacy First**: Your data stays with you\\n- **Markdown Support**: Full CommonMark + GFM syntax\\n- **Quick Capture**: Jot down thoughts instantly\\n- **Organize with Tags**: Use #tags to categorize\\n- **Open Source**: Free and open source software\\n\\n---\\n\\nStart exploring the demo memos below to see what you can do! #welcome #getting-started','\\n',char(10)),'PUBLIC',1,'{"tags":["welcome","getting-started"],"property":{"hasLink":false}}');

View File

@ -41,12 +41,11 @@ func NewTestingStore(ctx context.Context, t *testing.T) *store.Store {
// This is useful for testing migrations on existing data.
func NewTestingStoreWithDSN(_ context.Context, t *testing.T, driver, dsn string) *store.Store {
profile := &profile.Profile{
Mode: "prod",
Port: getUnusedPort(),
Data: t.TempDir(), // Dummy dir, DSN matters
DSN: dsn,
Driver: driver,
Version: version.GetCurrentVersion("prod"),
Version: version.GetCurrentVersion(),
}
dbDriver, err := db.NewDBDriver(profile)
if err != nil {
@ -95,12 +94,11 @@ func getTestingProfileForDriver(t *testing.T, driver string) *profile.Profile {
}
return &profile.Profile{
Mode: mode,
Port: port,
Data: dir,
DSN: dsn,
Driver: driver,
Version: version.GetCurrentVersion(mode),
Version: version.GetCurrentVersion(),
}
}

View File

@ -20,7 +20,7 @@ func TestUserStore(t *testing.T) {
users, err := ts.ListUsers(ctx, &store.FindUser{})
require.NoError(t, err)
require.Equal(t, 1, len(users))
require.Equal(t, store.RoleHost, users[0].Role)
require.Equal(t, store.RoleAdmin, users[0].Role)
require.Equal(t, user, users[0])
userPatchNickname := "test_nickname_2"
userPatch := &store.UpdateUser{
@ -104,7 +104,7 @@ func TestUserListByRole(t *testing.T) {
_, err := createTestingHostUser(ctx, ts)
require.NoError(t, err)
adminUser, err := createTestingUserWithRole(ctx, ts, "admin_user", store.RoleAdmin)
_, err = createTestingUserWithRole(ctx, ts, "admin_user", store.RoleAdmin)
require.NoError(t, err)
regularUser, err := createTestingUserWithRole(ctx, ts, "regular_user", store.RoleUser)
@ -115,19 +115,11 @@ func TestUserListByRole(t *testing.T) {
require.NoError(t, err)
require.Equal(t, 3, len(allUsers))
// List only HOST users
hostRole := store.RoleHost
hostUsers, err := ts.ListUsers(ctx, &store.FindUser{Role: &hostRole})
require.NoError(t, err)
require.Equal(t, 1, len(hostUsers))
require.Equal(t, store.RoleHost, hostUsers[0].Role)
// List only ADMIN users
adminRole := store.RoleAdmin
adminUsers, err := ts.ListUsers(ctx, &store.FindUser{Role: &adminRole})
adminOnlyUsers, err := ts.ListUsers(ctx, &store.FindUser{Role: &adminRole})
require.NoError(t, err)
require.Equal(t, 1, len(adminUsers))
require.Equal(t, adminUser.ID, adminUsers[0].ID)
require.Equal(t, 2, len(adminOnlyUsers))
// List only USER role users
userRole := store.RoleUser
@ -227,7 +219,7 @@ func TestUserListWithLimit(t *testing.T) {
for i := 0; i < 5; i++ {
role := store.RoleUser
if i == 0 {
role = store.RoleHost
role = store.RoleAdmin
}
_, err := createTestingUserWithRole(ctx, ts, fmt.Sprintf("user%d", i), role)
require.NoError(t, err)
@ -243,7 +235,7 @@ func TestUserListWithLimit(t *testing.T) {
}
func createTestingHostUser(ctx context.Context, ts *store.Store) (*store.User, error) {
return createTestingUserWithRole(ctx, ts, "test", store.RoleHost)
return createTestingUserWithRole(ctx, ts, "test", store.RoleAdmin)
}
func createTestingUserWithRole(ctx context.Context, ts *store.Store, username string, role store.Role) (*store.User, error) {

View File

@ -8,8 +8,6 @@ import (
type Role string
const (
// RoleHost is the HOST role.
RoleHost Role = "HOST"
// RoleAdmin is the ADMIN role.
RoleAdmin Role = "ADMIN"
// RoleUser is the USER role.
@ -18,8 +16,6 @@ const (
func (e Role) String() string {
switch e {
case RoleHost:
return "HOST"
case RoleAdmin:
return "ADMIN"
default:

View File

@ -31,9 +31,7 @@ const MemberSection = () => {
const [deleteTarget, setDeleteTarget] = useState<User | undefined>(undefined);
const stringifyUserRole = (role: User_Role) => {
if (role === User_Role.HOST) {
return "Host";
} else if (role === User_Role.ADMIN) {
if (role === User_Role.ADMIN) {
return t("setting.member-section.admin");
} else {
return t("setting.member-section.user");

View File

@ -45,7 +45,7 @@ const Setting = () => {
const [state, setState] = useState<State>({
selectedSection: "my-account",
});
const isHost = user?.role === User_Role.HOST;
const isHost = user?.role === User_Role.ADMIN;
const settingsSectionList = useMemo(() => {
let settingList = [...BASIC_SECTIONS];

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,5 @@
import { User, User_Role } from "@/types/proto/api/v1/user_service_pb";
export const isSuperUser = (user: User | undefined) => {
return user && (user.role === User_Role.ADMIN || user.role === User_Role.HOST);
return user && user.role === User_Role.ADMIN;
};