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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
class SessionsController < ApplicationController
allow_unauthenticated_access only: %i[ new create ]
rate_limit to: 10, within: 3.minutes, only: :create, with: -> {
flash.now[:alert] = "操作过频,请稍后重试"
render inertia: "sessions/New", props: { flash: flash.to_h }
}
def new
render inertia: "sessions/New", props: {
flash: flash.to_h
}
end
def create
if user = User.authenticate_by(params.permit(:email_address, :password))
start_new_session_for user
# Send notification email for new login if enabled
# if user.notify_on_new_login? && !from_familiar_device?(user)
# SessionMailer.new_login_notification(user, request.remote_ip, request.user_agent).deliver_later
# end
redirect_to after_authentication_url
else
# For Inertia.js, we need to render the component with flash messages
flash.now[:alert] = "账户或密码错误"
render inertia: "sessions/New", props: {
flash: flash.to_h
}
end
end
def destroy
terminate_session
redirect_to new_session_path, notice: "你已登出"
end
def index
@sessions = current_user.sessions.order(updated_at: :desc)
render inertia: "sessions/Index", props: {
sessions: @sessions.as_json(methods: [ :is_current ]),
flash: flash.to_h
}
end
def show
@session = current_user.sessions.find(params[:id])
render inertia: "sessions/Show", props: {
session: @session.as_json(methods: [ :is_current ]),
flash: flash.to_h
}
rescue ActiveRecord::RecordNotFound
redirect_to sessions_path, alert: "Session not found."
end
def destroy_session
@session = current_user.sessions.find(params[:id])
if @session.is_current?
redirect_to sessions_path, alert: "你不能终止当前会话。"
else
@session.destroy
redirect_to sessions_path, notice: "会话已终止。"
end
rescue ActiveRecord::RecordNotFound
redirect_to sessions_path, alert: "会话未找到。"
end
def terminate_all
current_user.sessions.where.not(id: current_session.id).destroy_all
redirect_to sessions_path, notice: "所有其他会话已终止。"
end
def security
render inertia: "sessions/Security", props: {
security_settings: current_user.security_settings,
flash: flash.to_h
}
end
def update_security
if current_user.update(security_params)
redirect_to security_sessions_path, notice: "安全设置已更新。"
else
render inertia: "sessions/Security", props: {
security_settings: current_user.security_settings,
errors: current_user.errors,
flash: flash.to_h
}
end
end
private
def from_familiar_device?(user)
# Check if this device has been used before by this user
user.sessions.where(user_agent: request.user_agent, ip_address: request.remote_ip).exists?
end
def security_params
params.require(:user).permit(
:require_two_factor,
:session_timeout_minutes,
:notify_on_new_login,
:max_sessions
)
end
end