mirror of
https://github.com/casdoor/casdoor.git
synced 2025-07-29 18:50:35 +08:00
Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
e3a43d0062 | ||
![]() |
0cf281cac0 | ||
![]() |
7322f67ae0 | ||
![]() |
b927c6d7b4 | ||
![]() |
01212cd1f3 |
@@ -475,6 +475,16 @@ func (c *ApiController) SetPassword() {
|
||||
|
||||
userId := util.GetId(userOwner, userName)
|
||||
|
||||
user, err := object.GetUser(userId)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
if user == nil {
|
||||
c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), userId))
|
||||
return
|
||||
}
|
||||
|
||||
requestUserId := c.GetSessionUsername()
|
||||
if requestUserId == "" && code == "" {
|
||||
c.ResponseError(c.T("general:Please login first"), "Please login first")
|
||||
@@ -518,7 +528,11 @@ func (c *ApiController) SetPassword() {
|
||||
}
|
||||
}
|
||||
} else if code == "" {
|
||||
err = object.CheckPassword(targetUser, oldPassword, c.GetAcceptLanguage())
|
||||
if user.Ldap == "" {
|
||||
err = object.CheckPassword(targetUser, oldPassword, c.GetAcceptLanguage())
|
||||
} else {
|
||||
err = object.CheckLdapUserPassword(targetUser, oldPassword, c.GetAcceptLanguage())
|
||||
}
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
@@ -563,7 +577,12 @@ func (c *ApiController) SetPassword() {
|
||||
targetUser.NeedUpdatePassword = false
|
||||
targetUser.LastChangePasswordTime = util.GetCurrentTime()
|
||||
|
||||
_, err = object.UpdateUser(userId, targetUser, []string{"password", "need_update_password", "password_type", "last_change_password_time"}, false)
|
||||
if user.Ldap == "" {
|
||||
_, err = object.UpdateUser(userId, targetUser, []string{"password", "need_update_password", "password_type", "last_change_password_time"}, false)
|
||||
} else {
|
||||
err = object.ResetLdapPassword(targetUser, newPassword, c.GetAcceptLanguage())
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
|
1
go.mod
1
go.mod
@@ -63,6 +63,7 @@ require (
|
||||
golang.org/x/crypto v0.21.0
|
||||
golang.org/x/net v0.21.0
|
||||
golang.org/x/oauth2 v0.17.0
|
||||
golang.org/x/text v0.14.0
|
||||
google.golang.org/api v0.150.0
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/square/go-jose.v2 v2.6.0
|
||||
|
@@ -273,7 +273,7 @@ func CheckPasswordComplexity(user *User, password string) string {
|
||||
return CheckPasswordComplexityByOrg(organization, password)
|
||||
}
|
||||
|
||||
func checkLdapUserPassword(user *User, password string, lang string) error {
|
||||
func CheckLdapUserPassword(user *User, password string, lang string) error {
|
||||
ldaps, err := GetLdaps(user.Owner)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -368,7 +368,7 @@ func CheckUserPassword(organization string, username string, password string, la
|
||||
}
|
||||
|
||||
// only for LDAP users
|
||||
err = checkLdapUserPassword(user, password, lang)
|
||||
err = CheckLdapUserPassword(user, password, lang)
|
||||
if err != nil {
|
||||
if err.Error() == "user not exist" {
|
||||
return nil, fmt.Errorf(i18n.Translate(lang, "check:The user: %s doesn't exist in LDAP server"), username)
|
||||
|
@@ -31,6 +31,9 @@ type Dashboard struct {
|
||||
CertCounts []int `json:"certCounts"`
|
||||
PermissionCounts []int `json:"permissionCounts"`
|
||||
TransactionCounts []int `json:"transactionCounts"`
|
||||
ModelCounts []int `json:"modelCounts"`
|
||||
AdapterCounts []int `json:"adapterCounts"`
|
||||
EnforcerCounts []int `json:"enforcerCounts"`
|
||||
}
|
||||
|
||||
func GetDashboard(owner string) (*Dashboard, error) {
|
||||
@@ -50,6 +53,9 @@ func GetDashboard(owner string) (*Dashboard, error) {
|
||||
CertCounts: make([]int, 31),
|
||||
PermissionCounts: make([]int, 31),
|
||||
TransactionCounts: make([]int, 31),
|
||||
ModelCounts: make([]int, 31),
|
||||
AdapterCounts: make([]int, 31),
|
||||
EnforcerCounts: make([]int, 31),
|
||||
}
|
||||
|
||||
organizations := []Organization{}
|
||||
@@ -63,9 +69,12 @@ func GetDashboard(owner string) (*Dashboard, error) {
|
||||
certs := []Cert{}
|
||||
permissions := []Permission{}
|
||||
transactions := []Transaction{}
|
||||
models := []Model{}
|
||||
adapters := []Adapter{}
|
||||
enforcers := []Enforcer{}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(11)
|
||||
wg.Add(14)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
if err := ormer.Engine.Find(&organizations, &Organization{Owner: owner}); err != nil {
|
||||
@@ -148,6 +157,27 @@ func GetDashboard(owner string) (*Dashboard, error) {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
if err := ormer.Engine.Find(&models, &Model{Owner: owner}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
if err := ormer.Engine.Find(&adapters, &Adapter{Owner: owner}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
if err := ormer.Engine.Find(&enforcers, &Enforcer{Owner: owner}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
wg.Wait()
|
||||
|
||||
nowTime := time.Now()
|
||||
@@ -164,6 +194,9 @@ func GetDashboard(owner string) (*Dashboard, error) {
|
||||
dashboard.CertCounts[30-i] = countCreatedBefore(certs, cutTime)
|
||||
dashboard.PermissionCounts[30-i] = countCreatedBefore(permissions, cutTime)
|
||||
dashboard.TransactionCounts[30-i] = countCreatedBefore(transactions, cutTime)
|
||||
dashboard.ModelCounts[30-i] = countCreatedBefore(models, cutTime)
|
||||
dashboard.AdapterCounts[30-i] = countCreatedBefore(adapters, cutTime)
|
||||
dashboard.EnforcerCounts[30-i] = countCreatedBefore(enforcers, cutTime)
|
||||
}
|
||||
return dashboard, nil
|
||||
}
|
||||
@@ -248,6 +281,27 @@ func countCreatedBefore(objects interface{}, before time.Time) int {
|
||||
count++
|
||||
}
|
||||
}
|
||||
case []Model:
|
||||
for _, m := range obj {
|
||||
createdTime, _ := time.Parse("2006-01-02T15:04:05-07:00", m.CreatedTime)
|
||||
if createdTime.Before(before) {
|
||||
count++
|
||||
}
|
||||
}
|
||||
case []Adapter:
|
||||
for _, a := range obj {
|
||||
createdTime, _ := time.Parse("2006-01-02T15:04:05-07:00", a.CreatedTime)
|
||||
if createdTime.Before(before) {
|
||||
count++
|
||||
}
|
||||
}
|
||||
case []Enforcer:
|
||||
for _, e := range obj {
|
||||
createdTime, _ := time.Parse("2006-01-02T15:04:05-07:00", e.CreatedTime)
|
||||
if createdTime.Before(before) {
|
||||
count++
|
||||
}
|
||||
}
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
@@ -20,9 +20,11 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/casdoor/casdoor/conf"
|
||||
"github.com/casdoor/casdoor/i18n"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
goldap "github.com/go-ldap/ldap/v3"
|
||||
"github.com/thanhpk/randstr"
|
||||
"golang.org/x/text/encoding/unicode"
|
||||
)
|
||||
|
||||
type LdapConn struct {
|
||||
@@ -371,6 +373,64 @@ func GetExistUuids(owner string, uuids []string) ([]string, error) {
|
||||
return existUuids, nil
|
||||
}
|
||||
|
||||
func ResetLdapPassword(user *User, newPassword string, lang string) error {
|
||||
ldaps, err := GetLdaps(user.Owner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, ldapServer := range ldaps {
|
||||
conn, err := ldapServer.GetLdapConn()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
searchReq := goldap.NewSearchRequest(ldapServer.BaseDn, goldap.ScopeWholeSubtree, goldap.NeverDerefAliases,
|
||||
0, 0, false, ldapServer.buildAuthFilterString(user), []string{}, nil)
|
||||
|
||||
searchResult, err := conn.Conn.Search(searchReq)
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
return err
|
||||
}
|
||||
|
||||
if len(searchResult.Entries) == 0 {
|
||||
conn.Close()
|
||||
continue
|
||||
}
|
||||
if len(searchResult.Entries) > 1 {
|
||||
conn.Close()
|
||||
return fmt.Errorf(i18n.Translate(lang, "check:Multiple accounts with same uid, please check your ldap server"))
|
||||
}
|
||||
|
||||
userDn := searchResult.Entries[0].DN
|
||||
|
||||
var pwdEncoded string
|
||||
modifyPasswordRequest := goldap.NewModifyRequest(userDn, nil)
|
||||
if conn.IsAD {
|
||||
utf16 := unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM)
|
||||
pwdEncoded, err := utf16.NewEncoder().String("\"" + newPassword + "\"")
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
return err
|
||||
}
|
||||
modifyPasswordRequest.Replace("unicodePwd", []string{pwdEncoded})
|
||||
modifyPasswordRequest.Replace("userAccountControl", []string{"512"})
|
||||
} else {
|
||||
pwdEncoded = newPassword
|
||||
modifyPasswordRequest.Replace("userPassword", []string{pwdEncoded})
|
||||
}
|
||||
|
||||
err = conn.Conn.Modify(modifyPasswordRequest)
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
return err
|
||||
}
|
||||
conn.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ldapUser *LdapUser) buildLdapUserName(owner string) (string, error) {
|
||||
user := User{}
|
||||
uidWithNumber := fmt.Sprintf("%s_%s", ldapUser.Uid, ldapUser.UidNumber)
|
||||
|
@@ -33,7 +33,7 @@ var (
|
||||
|
||||
func init() {
|
||||
logPostOnly = conf.GetConfigBool("logPostOnly")
|
||||
passwordRegex = regexp.MustCompile("\"password\":\".+\"")
|
||||
passwordRegex = regexp.MustCompile("\"password\":\"([^\"]*?)\"")
|
||||
}
|
||||
|
||||
type Record struct {
|
||||
|
@@ -504,7 +504,7 @@ func GetPasswordToken(application *Application, username string, password string
|
||||
}
|
||||
|
||||
if user.Ldap != "" {
|
||||
err = checkLdapUserPassword(user, password, "en")
|
||||
err = CheckLdapUserPassword(user, password, "en")
|
||||
} else {
|
||||
err = CheckPassword(user, password, "en")
|
||||
}
|
||||
|
@@ -308,7 +308,7 @@ class App extends Component {
|
||||
AI Assistant
|
||||
</a>
|
||||
</Tooltip>
|
||||
<a className="custom-link" style={{float: "right", marginTop: "2px"}} target="_blank" rel="noreferrer" href={"https://ai.casbin.com"}>
|
||||
<a className="custom-link" style={{float: "right", marginTop: "2px"}} target="_blank" rel="noreferrer" href={`${Conf.AiAssistantUrl}`}>
|
||||
<ShareAltOutlined className="custom-link" style={{fontSize: "20px", color: "rgb(140,140,140)"}} />
|
||||
</a>
|
||||
<a className="custom-link" style={{float: "right", marginRight: "30px", marginTop: "2px"}} target="_blank" rel="noreferrer" href={"https://github.com/casibase/casibase"}>
|
||||
@@ -326,7 +326,7 @@ class App extends Component {
|
||||
}}
|
||||
visible={this.state.isAiAssistantOpen}
|
||||
>
|
||||
<iframe id="iframeHelper" title={"iframeHelper"} src={"https://ai.casbin.com/?isRaw=1"} width="100%" height="100%" scrolling="no" frameBorder="no" />
|
||||
<iframe id="iframeHelper" title={"iframeHelper"} src={`${Conf.AiAssistantUrl}/?isRaw=1`} width="100%" height="100%" scrolling="no" frameBorder="no" />
|
||||
</Drawer>
|
||||
);
|
||||
}
|
||||
|
@@ -31,3 +31,6 @@ export const ThemeDefault = {
|
||||
};
|
||||
|
||||
export const CustomFooter = null;
|
||||
|
||||
// Blank or null to hide Ai Assistant button
|
||||
export const AiAssistantUrl = "https://ai.casbin.com";
|
||||
|
@@ -26,10 +26,12 @@ const IframeEditor = forwardRef(({initialModelText, onModelTextChange}, ref) =>
|
||||
onModelTextChange(event.data.modelText);
|
||||
} else if (event.data.type === "iframeReady") {
|
||||
setIframeReady(true);
|
||||
iframeRef.current?.contentWindow.postMessage({
|
||||
type: "initializeModel",
|
||||
modelText: initialModelText,
|
||||
}, "*");
|
||||
if (initialModelText && iframeRef.current?.contentWindow) {
|
||||
iframeRef.current.contentWindow.postMessage({
|
||||
type: "initializeModel",
|
||||
modelText: initialModelText,
|
||||
}, "*");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -39,11 +41,15 @@ const IframeEditor = forwardRef(({initialModelText, onModelTextChange}, ref) =>
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
getModelText: () => {
|
||||
iframeRef.current?.contentWindow.postMessage({type: "getModelText"}, "*");
|
||||
if (iframeRef.current?.contentWindow) {
|
||||
iframeRef.current.contentWindow.postMessage({
|
||||
type: "getModelText",
|
||||
}, "*");
|
||||
}
|
||||
},
|
||||
updateModelText: (newModelText) => {
|
||||
if (iframeReady) {
|
||||
iframeRef.current?.contentWindow.postMessage({
|
||||
if (iframeReady && iframeRef.current?.contentWindow) {
|
||||
iframeRef.current.contentWindow.postMessage({
|
||||
type: "updateModelText",
|
||||
modelText: newModelText,
|
||||
}, "*");
|
||||
|
@@ -192,11 +192,15 @@ function ManagementPage(props) {
|
||||
themeAlgorithm={props.themeAlgorithm}
|
||||
onChange={props.setLogoAndThemeAlgorithm} />
|
||||
<LanguageSelect languages={props.account.organization.languages} />
|
||||
<Tooltip title="Click to open AI assitant">
|
||||
<div className="select-box" onClick={props.openAiAssistant}>
|
||||
<DeploymentUnitOutlined style={{fontSize: "24px"}} />
|
||||
</div>
|
||||
</Tooltip>
|
||||
{
|
||||
Conf.AiAssistantUrl?.trim() && (
|
||||
<Tooltip title="Click to open AI assistant">
|
||||
<div className="select-box" onClick={props.openAiAssistant}>
|
||||
<DeploymentUnitOutlined style={{fontSize: "24px"}} />
|
||||
</div>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
<OpenTour />
|
||||
{Setting.isAdminUser(props.account) && (props.uri.indexOf("/trees") === -1) &&
|
||||
<OrganizationSelect
|
||||
|
@@ -141,6 +141,9 @@ const Dashboard = (props) => {
|
||||
i18next.t("general:Certs"),
|
||||
i18next.t("general:Permissions"),
|
||||
i18next.t("general:Transactions"),
|
||||
i18next.t("general:Models"),
|
||||
i18next.t("general:Adapters"),
|
||||
i18next.t("general:Enforcers"),
|
||||
], top: "10%"},
|
||||
grid: {left: "3%", right: "4%", bottom: "0", top: "25%", containLabel: true},
|
||||
xAxis: {type: "category", boundaryGap: false, data: dateArray},
|
||||
@@ -157,6 +160,9 @@ const Dashboard = (props) => {
|
||||
{name: i18next.t("general:Certs"), type: "line", data: dashboardData.certCounts},
|
||||
{name: i18next.t("general:Permissions"), type: "line", data: dashboardData.permissionCounts},
|
||||
{name: i18next.t("general:Transactions"), type: "line", data: dashboardData.transactionCounts},
|
||||
{name: i18next.t("general:Models"), type: "line", data: dashboardData.modelCounts},
|
||||
{name: i18next.t("general:Adapters"), type: "line", data: dashboardData.adapterCounts},
|
||||
{name: i18next.t("general:Enforcers"), type: "line", data: dashboardData.enforcerCounts},
|
||||
],
|
||||
};
|
||||
myChart.setOption(option);
|
||||
|
Reference in New Issue
Block a user