コンテンツにスキップ

ありがとうございます。

ここから 第16段階:管理者機能強化(ユーザー管理・権限管理・監査管理・システム管理)設計 に進みます。

ここまでで、

  • 教材作成

  • 教材審査

  • 公開

  • 受講管理

  • 教材ライブラリ

まで構築できています。

しかし、実際の教育サービス運営では管理者が以下を管理できる必要があります。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
管理者

├ ユーザー管理
│   ├ 受講者登録
│   ├ 教師登録
│   └ 無効化
│
├ 権限管理
│   ├ Role
│   └ Permission
│
├ 教材管理
│   ├ 承認
│   ├ 公開
│   └ 非公開
│
├ 監査管理
│   └ 操作履歴確認
│
└ システム設定

第16段階 全体構成

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
                    ADMIN

                      |
        +-------------+-------------+

        User管理                  Content管理

          |                         |

     Role / Permission          Approval


                      |

                 AuditLog

                      |

              SystemSetting

1. ユーザー管理設計

現在

1
2
3
4
5
6
7
8
9
users

id

name

email

password

ですが、運用では以下が必要です。


追加項目:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
状態

有効
停止
退会


最終ログイン日時


登録日時


更新日時

2. Userテーブル拡張

1
2
3
4
5
ALTER TABLE users ADD COLUMN status VARCHAR(30);

ALTER TABLE users ADD COLUMN last_login_at DATETIME;

ALTER TABLE users ADD COLUMN updated_at DATETIME;

3. UserStatus

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
public enum UserStatus {

    ACTIVE,

    INACTIVE,

    LOCKED,

    DELETED

}

4. User Entity

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
@Entity
@Table(name="users")
@Getter
@Setter
public class User {


    @Id
    @GeneratedValue(
        strategy=GenerationType.IDENTITY
    )
    private Long id;


    private String username;


    private String email;


    private String password;


    @Enumerated(EnumType.STRING)
    private UserStatus status;


    private LocalDateTime lastLoginAt;


    private LocalDateTime createdAt;


    private LocalDateTime updatedAt;


    @ManyToMany(fetch=FetchType.EAGER)
    @JoinTable(
        name="user_roles",
        joinColumns=@JoinColumn(
            name="user_id"
        ),
        inverseJoinColumns=@JoinColumn(
            name="role_id"
        )
    )
    private Set<Role> roles;

}

5. Role管理

現在:

1
2
3
4
5
6
7
ADMIN

TEACHER

MENTOR

STUDENT

ですが、将来的には増える可能性があります。

そのためDB管理します。


6. Roleテーブル

1
2
3
4
5
6
7
8
9
CREATE TABLE roles (

id BIGINT AUTO_INCREMENT PRIMARY KEY,

code VARCHAR(50) UNIQUE,

name VARCHAR(100)

);

データ:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
INSERT INTO roles
(code,name)
VALUES

('ADMIN','管理者'),

('TEACHER','教師'),

('MENTOR','メンター'),

('STUDENT','受講者');

7. UserRole

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
CREATE TABLE user_roles (

user_id BIGINT,

role_id BIGINT,

PRIMARY KEY(
user_id,
role_id
)

);

8. Permission設計

Roleだけでは細かい制御が難しくなります。

例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
教師A

教材作成 ○

教材削除 ×


教師管理者

教材削除 ○

そこでPermissionを追加します。


9. Permissionテーブル

1
2
3
4
5
6
7
8
9
CREATE TABLE permissions (

id BIGINT AUTO_INCREMENT PRIMARY KEY,

code VARCHAR(100),

name VARCHAR(100)

);

例:

1
2
3
4
5
6
7
8
9
CONTENT_CREATE

CONTENT_UPDATE

CONTENT_APPROVE

USER_MANAGE

AUDIT_VIEW

10. RolePermission

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
CREATE TABLE role_permissions (

role_id BIGINT,

permission_id BIGINT,

PRIMARY KEY(
role_id,
permission_id
)

);

11. 権限モデル

完成形:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
User

 |

UserRole

 |

Role

 |

RolePermission

 |

Permission

12. Permissionチェック

Spring Securityでは、

Role:

1
hasRole()

Permission:

1
hasAuthority()

を利用します。


例:

1
2
3
4
5
@PreAuthorize(
"hasAuthority('CONTENT_APPROVE')")
public void approve(){

}

13. CustomUserDetails変更

現在:

1
ROLE_ADMIN

だけでした。

追加:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
@Override
public Collection<? extends GrantedAuthority>
getAuthorities(){


Set<GrantedAuthority> authorities =
new HashSet<>();


user.getRoles()
.forEach(role -> {


authorities.add(
new SimpleGrantedAuthority(
"ROLE_"+role.getCode()
)
);


role.getPermissions()
.forEach(permission -> {

authorities.add(
new SimpleGrantedAuthority(
permission.getCode()
)
);

});


});


return authorities;

}

14. 管理者ユーザー管理画面

URL:

1
/admin/users

画面:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
------------------------------------------------

名前       Email        Role       状態

山田       xxx@test     TEACHER    有効

佐藤       xxx@test     STUDENT    有効


[編集]

------------------------------------------------

15. User一覧DTO

MyBatis利用。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Data
public class UserListDto {


private Long id;


private String username;


private String email;


private String roles;


private String status;


private LocalDateTime createdAt;


}

16. UserMapper

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
@Mapper
public interface UserMapper {


List<UserListDto> search(
    UserSearchCondition condition
);


}

17. User検索条件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
@Data
public class UserSearchCondition {


private String keyword;


private String role;


private String status;


private Integer page=0;


private Integer size=20;


}

18. 教材承認管理改善

現在:

1
審査中一覧

だけでした。

改善:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
管理者

承認待ち

↓

詳細確認

↓

差戻し理由入力

↓

承認

19. ApprovalHistory追加

承認履歴を残します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
CREATE TABLE approval_histories (

id BIGINT AUTO_INCREMENT PRIMARY KEY,

content_version_id BIGINT,

approver_id BIGINT,

action VARCHAR(30),

comment TEXT,

created_at DATETIME

);

状態:

1
2
3
APPROVE

REJECT

を記録します。


20. Audit検索画面

URL:

1
/admin/audit

検索:

1
2
3
4
5
6
7
期間

ユーザー

操作種類

対象

例:

1
2
3
4
5
6
7
2026/08/01

山田先生

PUBLISH

教材ID:100

21. AuditSearchCondition

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
@Data
public class AuditSearchCondition {


private Long userId;


private String actionType;


private String targetType;


private LocalDateTime from;


private LocalDateTime to;


}

22. システム設定管理

将来変更される値をDB管理します。

例:

1
2
3
4
5
6
7
1ページ表示件数

動画最大容量

公開承認必須

修了条件

23. SystemSettingテーブル

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
CREATE TABLE system_settings (

id BIGINT AUTO_INCREMENT PRIMARY KEY,

setting_key VARCHAR(100),

setting_value TEXT,

description VARCHAR(255)

);

データ例:

1
2
3
4
5
6
7
INSERT INTO system_settings
(setting_key,setting_value)
VALUES

('CONTENT_APPROVAL_REQUIRED','true'),

('DEFAULT_PAGE_SIZE','20');

24. Admin Dashboard

表示:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
教材

----------------

総教材数

520


公開中

430


審査中

15



ユーザー

----------------

教師

30


受講者

2000

25. Dashboard DTO

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Data
public class AdminDashboardDto {


private Integer userCount;


private Integer teacherCount;


private Integer studentCount;


private Integer contentCount;


private Integer reviewCount;


private Integer publishedCount;


}

26. 管理者URL構成

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/admin

├ dashboard

├ users

│  ├ list

│  └ edit


├ contents

│  └ approval


├ audit

│  └ list


├ roles

│  └ list


└ settings

   └ list

27. 第16段階終了後の権限構造

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
                    User

                      |

                    Role

                      |

              Permission


ADMIN

 ├ USER_MANAGE

 ├ CONTENT_APPROVE

 ├ AUDIT_VIEW


TEACHER

 ├ CONTENT_CREATE

 ├ CONTENT_UPDATE


MENTOR

 ├ STUDENT_VIEW


STUDENT

 ├ CONTENT_VIEW

 └ LEARNING_UPDATE

第16段階終了時点

追加された機能:

✅ ユーザー管理
✅ Role管理
✅ Permission管理
✅ 詳細権限制御
✅ 承認履歴管理
✅ 監査ログ検索
✅ システム設定管理
✅ 管理者ダッシュボード


次の 第17段階 では、システム品質を高めるために以下を設計します。

第17段階:共通基盤・運用機能

内容:

  1. 例外処理(@ControllerAdvice)

  2. エラー画面

  3. バリデーション共通化

  4. メッセージ管理

  5. トランザクション設計

  6. Spring AOP共通処理整理

  7. ログ設計

  8. バッチ処理

  9. メール通知設計

まで進めます。