1
1
from typing import cast
2
2
3
3
import flask_login
4
- from flask import request
4
+ from flask import redirect , request
5
5
from flask_restful import Resource , reqparse
6
6
7
7
import services
8
+ from configs import dify_config
9
+ from constants .languages import languages
8
10
from controllers .console import api
11
+ from controllers .console .auth .error import (
12
+ EmailCodeError ,
13
+ InvalidEmailError ,
14
+ InvalidTokenError ,
15
+ )
9
16
from controllers .console .setup import setup_required
10
17
from libs .helper import email , get_remote_ip
11
18
from libs .password import valid_password
@@ -25,12 +32,14 @@ def post(self):
25
32
parser .add_argument ("remember_me" , type = bool , required = False , default = False , location = "json" )
26
33
args = parser .parse_args ()
27
34
28
- # todo: Verify the recaptcha
29
-
30
35
try :
31
36
account = AccountService .authenticate (args ["email" ], args ["password" ])
32
37
except services .errors .account .AccountLoginError as e :
33
- return {"code" : "unauthorized" , "message" : str (e )}, 401
38
+ if dify_config .ALLOW_REGISTER :
39
+ token = AccountService .send_reset_password_email (email = args ["email" ])
40
+ return redirect (f"{ dify_config .CONSOLE_WEB_URL } /reset-password?token={ token } " )
41
+ else :
42
+ return {"code" : "unauthorized" , "message" : str (e )}, 401
34
43
35
44
# SELF_HOSTED only have one workspace
36
45
tenants = TenantService .get_join_tenants (account )
@@ -55,56 +64,76 @@ def get(self):
55
64
return {"result" : "success" }
56
65
57
66
58
- class ResetPasswordApi (Resource ):
67
+ class ResetPasswordSendEmailApi (Resource ):
59
68
@setup_required
60
- def get (self ):
61
- # parser = reqparse.RequestParser()
62
- # parser.add_argument('email', type=email, required=True, location='json')
63
- # args = parser.parse_args()
64
-
65
- # import mailchimp_transactional as MailchimpTransactional
66
- # from mailchimp_transactional.api_client import ApiClientError
67
-
68
- # account = {'email': args['email']}
69
- # account = AccountService.get_by_email(args['email'])
70
- # if account is None:
71
- # raise ValueError('Email not found')
72
- # new_password = AccountService.generate_password()
73
- # AccountService.update_password(account, new_password)
74
-
75
- # todo: Send email
76
- # MAILCHIMP_API_KEY = dify_config.MAILCHIMP_TRANSACTIONAL_API_KEY
77
- # mailchimp = MailchimpTransactional(MAILCHIMP_API_KEY)
78
-
79
- # message = {
80
- # 'from_email': '[email protected] ',
81
- # 'to': [{'email': account['email']}],
82
- # 'subject': 'Reset your Dify password',
83
- # 'html': """
84
- # <p>Dear User,</p>
85
- # <p>The Dify team has generated a new password for you, details as follows:</p>
86
- # <p><strong>{new_password}</strong></p>
87
- # <p>Please change your password to log in as soon as possible.</p>
88
- # <p>Regards,</p>
89
- # <p>The Dify Team</p>
90
- # """
91
- # }
92
-
93
- # response = mailchimp.messages.send({
94
- # 'message': message,
95
- # # required for transactional email
96
- # ' settings': {
97
- # 'sandbox_mode': dify_config.MAILCHIMP_SANDBOX_MODE,
98
- # },
99
- # })
100
-
101
- # Check if MSG was sent
102
- # if response.status_code != 200:
103
- # # handle error
104
- # pass
69
+ def post (self ):
70
+ parser = reqparse .RequestParser ()
71
+ parser .add_argument ("email" , type = email , required = True , location = "json" )
72
+ args = parser .parse_args ()
105
73
106
- return {"result" : "success" }
74
+ account = AccountService .get_user_through_email (args ["email" ])
75
+ if account is None :
76
+ if dify_config .ALLOW_REGISTER :
77
+ token = AccountService .send_reset_password_email (email = args ["email" ])
78
+ else :
79
+ raise InvalidEmailError ()
80
+ else :
81
+ token = AccountService .send_reset_password_email (account = account )
82
+
83
+ return {"result" : "success" , "data" : token }
84
+
85
+
86
+ class EmailCodeLoginSendEmailApi (Resource ):
87
+ @setup_required
88
+ def post (self ):
89
+ parser = reqparse .RequestParser ()
90
+ parser .add_argument ("email" , type = email , required = True , location = "json" )
91
+ args = parser .parse_args ()
92
+
93
+ account = AccountService .get_user_through_email (args ["email" ])
94
+ if account is None :
95
+ token = AccountService .send_email_code_login_email (email = args ["email" ])
96
+ else :
97
+ token = AccountService .send_email_code_login_email (account = account )
98
+
99
+ return {"result" : "success" , "data" : token }
100
+
101
+
102
+ class EmailCodeLoginApi (Resource ):
103
+ @setup_required
104
+ def post (self ):
105
+ parser = reqparse .RequestParser ()
106
+ parser .add_argument ("email" , type = str , required = True , location = "json" )
107
+ parser .add_argument ("code" , type = str , required = True , location = "json" )
108
+ parser .add_argument ("token" , type = str , required = True , location = "json" )
109
+ args = parser .parse_args ()
110
+
111
+ user_email = args ["email" ]
112
+
113
+ token_data = AccountService .get_email_code_login_data (args ["token" ])
114
+ if token_data is None :
115
+ raise InvalidTokenError ()
116
+
117
+ if token_data ["email" ] != args ["email" ]:
118
+ raise InvalidEmailError ()
119
+
120
+ if token_data ["code" ] != args ["code" ]:
121
+ raise EmailCodeError ()
122
+
123
+ AccountService .revoke_email_code_login_token (args ["token" ])
124
+ account = AccountService .get_user_through_email (user_email )
125
+ if account is None :
126
+ account = AccountService .create_user_through_env (
127
+ email = user_email , name = user_email , interface_language = languages [0 ]
128
+ )
129
+
130
+ token = AccountService .login (account , ip_address = get_remote_ip (request ))
131
+
132
+ return {"result" : "success" , "data" : token }
107
133
108
134
109
135
api .add_resource (LoginApi , "/login" )
110
136
api .add_resource (LogoutApi , "/logout" )
137
+ api .add_resource (EmailCodeLoginSendEmailApi , "/email-code-login" )
138
+ api .add_resource (EmailCodeLoginApi , "/email-code-login/validity" )
139
+ api .add_resource (ResetPasswordSendEmailApi , "/reset-password" )
0 commit comments