mirror of
https://github.com/casdoor/casdoor.git
synced 2025-05-23 02:35:49 +08:00
feat: Add Invitation Code to Generate Invitation Link (#2666)
Add auto-population of invitation fields in the registration page based on the invitation code in the link
This commit is contained in:
parent
bbbda1982f
commit
b7be1943fa
@ -96,6 +96,7 @@ p, *, *, GET, /api/get-organization-names, *, *
|
|||||||
p, *, *, GET, /api/get-all-objects, *, *
|
p, *, *, GET, /api/get-all-objects, *, *
|
||||||
p, *, *, GET, /api/get-all-actions, *, *
|
p, *, *, GET, /api/get-all-actions, *, *
|
||||||
p, *, *, GET, /api/get-all-roles, *, *
|
p, *, *, GET, /api/get-all-roles, *, *
|
||||||
|
p, *, *, GET, /api/get-invitation-info, *, *
|
||||||
`
|
`
|
||||||
|
|
||||||
sa := stringadapter.NewAdapter(ruleText)
|
sa := stringadapter.NewAdapter(ruleText)
|
||||||
|
@ -227,7 +227,7 @@ func (c *ApiController) Signup() {
|
|||||||
|
|
||||||
if invitation != nil {
|
if invitation != nil {
|
||||||
invitation.UsedCount += 1
|
invitation.UsedCount += 1
|
||||||
_, err := object.UpdateInvitation(invitation.GetId(), invitation)
|
_, err := object.UpdateInvitation(invitation.GetId(), invitation, c.GetAcceptLanguage())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
|
@ -84,6 +84,32 @@ func (c *ApiController) GetInvitation() {
|
|||||||
c.ResponseOk(invitation)
|
c.ResponseOk(invitation)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetInvitationCodeInfo
|
||||||
|
// @Title GetInvitationCodeInfo
|
||||||
|
// @Tag Invitation API
|
||||||
|
// @Description get invitation code information
|
||||||
|
// @Param code query string true "Invitation code"
|
||||||
|
// @Success 200 {object} object.Invitation The Response object
|
||||||
|
// @router /get-invitation-info [get]
|
||||||
|
func (c *ApiController) GetInvitationCodeInfo() {
|
||||||
|
code := c.Input().Get("code")
|
||||||
|
applicationId := c.Input().Get("applicationId")
|
||||||
|
|
||||||
|
application, err := object.GetApplication(applicationId)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
invitation, msg := object.GetInvitationByCode(code, application.Organization, c.GetAcceptLanguage())
|
||||||
|
if msg != "" {
|
||||||
|
c.ResponseError(msg)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.ResponseOk(object.GetMaskedInvitation(invitation))
|
||||||
|
}
|
||||||
|
|
||||||
// UpdateInvitation
|
// UpdateInvitation
|
||||||
// @Title UpdateInvitation
|
// @Title UpdateInvitation
|
||||||
// @Tag Invitation API
|
// @Tag Invitation API
|
||||||
@ -102,7 +128,7 @@ func (c *ApiController) UpdateInvitation() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = wrapActionResponse(object.UpdateInvitation(id, &invitation))
|
c.Data["json"] = wrapActionResponse(object.UpdateInvitation(id, &invitation, c.GetAcceptLanguage()))
|
||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,7 +147,7 @@ func (c *ApiController) AddInvitation() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = wrapActionResponse(object.AddInvitation(&invitation))
|
c.Data["json"] = wrapActionResponse(object.AddInvitation(&invitation, c.GetAcceptLanguage()))
|
||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||||
"Email already exists": "Email already exists",
|
"Email already exists": "Email already exists",
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Zugehörigkeit darf nicht leer sein",
|
"Affiliation cannot be blank": "Zugehörigkeit darf nicht leer sein",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "Anzeigename kann nicht leer sein",
|
"DisplayName cannot be blank": "Anzeigename kann nicht leer sein",
|
||||||
"DisplayName is not valid real name": "DisplayName ist kein gültiger Vorname",
|
"DisplayName is not valid real name": "DisplayName ist kein gültiger Vorname",
|
||||||
"Email already exists": "E-Mail existiert bereits",
|
"Email already exists": "E-Mail existiert bereits",
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||||
"Email already exists": "Email already exists",
|
"Email already exists": "Email already exists",
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Afiliación no puede estar en blanco",
|
"Affiliation cannot be blank": "Afiliación no puede estar en blanco",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "El nombre de visualización no puede estar en blanco",
|
"DisplayName cannot be blank": "El nombre de visualización no puede estar en blanco",
|
||||||
"DisplayName is not valid real name": "El nombre de pantalla no es un nombre real válido",
|
"DisplayName is not valid real name": "El nombre de pantalla no es un nombre real válido",
|
||||||
"Email already exists": "El correo electrónico ya existe",
|
"Email already exists": "El correo electrónico ya existe",
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||||
"Email already exists": "Email already exists",
|
"Email already exists": "Email already exists",
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||||
"Email already exists": "Email already exists",
|
"Email already exists": "Email already exists",
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Affiliation ne peut pas être vide",
|
"Affiliation cannot be blank": "Affiliation ne peut pas être vide",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "Le nom d'affichage ne peut pas être vide",
|
"DisplayName cannot be blank": "Le nom d'affichage ne peut pas être vide",
|
||||||
"DisplayName is not valid real name": "DisplayName n'est pas un nom réel valide",
|
"DisplayName is not valid real name": "DisplayName n'est pas un nom réel valide",
|
||||||
"Email already exists": "E-mail déjà existant",
|
"Email already exists": "E-mail déjà existant",
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||||
"Email already exists": "Email already exists",
|
"Email already exists": "Email already exists",
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Keterkaitan tidak boleh kosong",
|
"Affiliation cannot be blank": "Keterkaitan tidak boleh kosong",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "Nama Pengguna tidak boleh kosong",
|
"DisplayName cannot be blank": "Nama Pengguna tidak boleh kosong",
|
||||||
"DisplayName is not valid real name": "DisplayName bukanlah nama asli yang valid",
|
"DisplayName is not valid real name": "DisplayName bukanlah nama asli yang valid",
|
||||||
"Email already exists": "Email sudah ada",
|
"Email already exists": "Email sudah ada",
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||||
"Email already exists": "Email already exists",
|
"Email already exists": "Email already exists",
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "所属は空白にできません",
|
"Affiliation cannot be blank": "所属は空白にできません",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "表示名は空白にできません",
|
"DisplayName cannot be blank": "表示名は空白にできません",
|
||||||
"DisplayName is not valid real name": "表示名は有効な実名ではありません",
|
"DisplayName is not valid real name": "表示名は有効な実名ではありません",
|
||||||
"Email already exists": "メールは既に存在します",
|
"Email already exists": "メールは既に存在します",
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||||
"Email already exists": "Email already exists",
|
"Email already exists": "Email already exists",
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "소속은 비워 둘 수 없습니다",
|
"Affiliation cannot be blank": "소속은 비워 둘 수 없습니다",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "DisplayName는 비어 있을 수 없습니다",
|
"DisplayName cannot be blank": "DisplayName는 비어 있을 수 없습니다",
|
||||||
"DisplayName is not valid real name": "DisplayName는 유효한 실제 이름이 아닙니다",
|
"DisplayName is not valid real name": "DisplayName는 유효한 실제 이름이 아닙니다",
|
||||||
"Email already exists": "이메일이 이미 존재합니다",
|
"Email already exists": "이메일이 이미 존재합니다",
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||||
"Email already exists": "Email already exists",
|
"Email already exists": "Email already exists",
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||||
"Email already exists": "Email already exists",
|
"Email already exists": "Email already exists",
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||||
"Email already exists": "Email already exists",
|
"Email already exists": "Email already exists",
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||||
"Email already exists": "Email already exists",
|
"Email already exists": "Email already exists",
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Принадлежность не может быть пустым значением",
|
"Affiliation cannot be blank": "Принадлежность не может быть пустым значением",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "Имя отображения не может быть пустым",
|
"DisplayName cannot be blank": "Имя отображения не может быть пустым",
|
||||||
"DisplayName is not valid real name": "DisplayName не является действительным именем",
|
"DisplayName is not valid real name": "DisplayName не является действительным именем",
|
||||||
"Email already exists": "Электронная почта уже существует",
|
"Email already exists": "Электронная почта уже существует",
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||||
"Email already exists": "Email already exists",
|
"Email already exists": "Email already exists",
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||||
"Email already exists": "Email already exists",
|
"Email already exists": "Email already exists",
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||||
"Email already exists": "Email already exists",
|
"Email already exists": "Email already exists",
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Tình trạng liên kết không thể để trống",
|
"Affiliation cannot be blank": "Tình trạng liên kết không thể để trống",
|
||||||
|
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
|
||||||
"DisplayName cannot be blank": "Tên hiển thị không thể để trống",
|
"DisplayName cannot be blank": "Tên hiển thị không thể để trống",
|
||||||
"DisplayName is not valid real name": "DisplayName không phải là tên thật hợp lệ",
|
"DisplayName is not valid real name": "DisplayName không phải là tên thật hợp lệ",
|
||||||
"Email already exists": "Email đã tồn tại",
|
"Email already exists": "Email đã tồn tại",
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "工作单位不可为空",
|
"Affiliation cannot be blank": "工作单位不可为空",
|
||||||
|
"Default code does not match the code's matching rules": "邀请码默认值和邀请码规则不匹配",
|
||||||
"DisplayName cannot be blank": "显示名称不可为空",
|
"DisplayName cannot be blank": "显示名称不可为空",
|
||||||
"DisplayName is not valid real name": "显示名称必须是真实姓名",
|
"DisplayName is not valid real name": "显示名称必须是真实姓名",
|
||||||
"Email already exists": "该邮箱已存在",
|
"Email already exists": "该邮箱已存在",
|
||||||
|
@ -184,6 +184,15 @@ func CheckInvitationCode(application *Application, organization *Organization, a
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CheckInvitationDefaultCode(code string, defaultCode string, lang string) error {
|
||||||
|
if matched, err := util.IsInvitationCodeMatch(code, defaultCode); err != nil {
|
||||||
|
return err
|
||||||
|
} else if !matched {
|
||||||
|
return fmt.Errorf(i18n.Translate(lang, "check:Default code does not match the code's matching rules"))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func checkSigninErrorTimes(user *User, lang string) error {
|
func checkSigninErrorTimes(user *User, lang string) error {
|
||||||
failedSigninLimit, failedSigninFrozenTime, err := GetFailedSigninConfigByUser(user)
|
failedSigninLimit, failedSigninFrozenTime, err := GetFailedSigninConfigByUser(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -40,6 +40,7 @@ type Invitation struct {
|
|||||||
Phone string `xorm:"varchar(100)" json:"phone"`
|
Phone string `xorm:"varchar(100)" json:"phone"`
|
||||||
|
|
||||||
SignupGroup string `xorm:"varchar(100)" json:"signupGroup"`
|
SignupGroup string `xorm:"varchar(100)" json:"signupGroup"`
|
||||||
|
DefaultCode string `xorm:"varchar(100)" json:"defaultCode"`
|
||||||
|
|
||||||
State string `xorm:"varchar(100)" json:"state"`
|
State string `xorm:"varchar(100)" json:"state"`
|
||||||
}
|
}
|
||||||
@ -93,7 +94,45 @@ func GetInvitation(id string) (*Invitation, error) {
|
|||||||
return getInvitation(owner, name)
|
return getInvitation(owner, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpdateInvitation(id string, invitation *Invitation) (bool, error) {
|
func GetInvitationByCode(code string, organizationName string, lang string) (*Invitation, string) {
|
||||||
|
invitations, err := GetInvitations(organizationName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err.Error()
|
||||||
|
}
|
||||||
|
errMsg := ""
|
||||||
|
for _, invitation := range invitations {
|
||||||
|
if isValid, msg := invitation.SimpleCheckInvitationCode(code, lang); isValid {
|
||||||
|
return invitation, msg
|
||||||
|
} else if msg != "" && errMsg == "" {
|
||||||
|
errMsg = msg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if errMsg != "" {
|
||||||
|
return nil, errMsg
|
||||||
|
} else {
|
||||||
|
return nil, i18n.Translate(lang, "check:Invitation code is invalid")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetMaskedInvitation(invitation *Invitation) *Invitation {
|
||||||
|
if invitation == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
invitation.CreatedTime = ""
|
||||||
|
invitation.UpdatedTime = ""
|
||||||
|
invitation.Code = "***"
|
||||||
|
invitation.DefaultCode = "***"
|
||||||
|
invitation.IsRegexp = false
|
||||||
|
invitation.Quota = -1
|
||||||
|
invitation.UsedCount = -1
|
||||||
|
invitation.SignupGroup = ""
|
||||||
|
|
||||||
|
return invitation
|
||||||
|
}
|
||||||
|
|
||||||
|
func UpdateInvitation(id string, invitation *Invitation, lang string) (bool, error) {
|
||||||
owner, name := util.GetOwnerAndNameFromId(id)
|
owner, name := util.GetOwnerAndNameFromId(id)
|
||||||
if p, err := getInvitation(owner, name); err != nil {
|
if p, err := getInvitation(owner, name); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@ -107,6 +146,11 @@ func UpdateInvitation(id string, invitation *Invitation) (bool, error) {
|
|||||||
invitation.IsRegexp = isRegexp
|
invitation.IsRegexp = isRegexp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err := CheckInvitationDefaultCode(invitation.Code, invitation.DefaultCode, lang)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
affected, err := ormer.Engine.ID(core.PK{owner, name}).AllCols().Update(invitation)
|
affected, err := ormer.Engine.ID(core.PK{owner, name}).AllCols().Update(invitation)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@ -115,13 +159,18 @@ func UpdateInvitation(id string, invitation *Invitation) (bool, error) {
|
|||||||
return affected != 0, nil
|
return affected != 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddInvitation(invitation *Invitation) (bool, error) {
|
func AddInvitation(invitation *Invitation, lang string) (bool, error) {
|
||||||
if isRegexp, err := util.IsRegexp(invitation.Code); err != nil {
|
if isRegexp, err := util.IsRegexp(invitation.Code); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
} else {
|
} else {
|
||||||
invitation.IsRegexp = isRegexp
|
invitation.IsRegexp = isRegexp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err := CheckInvitationDefaultCode(invitation.Code, invitation.DefaultCode, lang)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
affected, err := ormer.Engine.Insert(invitation)
|
affected, err := ormer.Engine.Insert(invitation)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@ -147,7 +196,7 @@ func VerifyInvitation(id string) (payment *Payment, attachInfo map[string]interf
|
|||||||
return nil, nil, fmt.Errorf("the invitation: %s does not exist", id)
|
return nil, nil, fmt.Errorf("the invitation: %s does not exist", id)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (invitation *Invitation) IsInvitationCodeValid(application *Application, invitationCode string, username string, email string, phone string, lang string) (bool, string) {
|
func (invitation *Invitation) SimpleCheckInvitationCode(invitationCode string, lang string) (bool, string) {
|
||||||
if matched, err := util.IsInvitationCodeMatch(invitation.Code, invitationCode); err != nil {
|
if matched, err := util.IsInvitationCodeMatch(invitation.Code, invitationCode); err != nil {
|
||||||
return false, err.Error()
|
return false, err.Error()
|
||||||
} else if !matched {
|
} else if !matched {
|
||||||
@ -160,15 +209,6 @@ func (invitation *Invitation) IsInvitationCodeValid(application *Application, in
|
|||||||
if invitation.UsedCount >= invitation.Quota {
|
if invitation.UsedCount >= invitation.Quota {
|
||||||
return false, i18n.Translate(lang, "check:Invitation code exhausted")
|
return false, i18n.Translate(lang, "check:Invitation code exhausted")
|
||||||
}
|
}
|
||||||
if application.IsSignupItemRequired("Username") && invitation.Username != "" && invitation.Username != username {
|
|
||||||
return false, i18n.Translate(lang, "check:Please register using the username corresponding to the invitation code")
|
|
||||||
}
|
|
||||||
if application.IsSignupItemRequired("Email") && invitation.Email != "" && invitation.Email != email {
|
|
||||||
return false, i18n.Translate(lang, "check:Please register using the email corresponding to the invitation code")
|
|
||||||
}
|
|
||||||
if application.IsSignupItemRequired("Phone") && invitation.Phone != "" && invitation.Phone != phone {
|
|
||||||
return false, i18n.Translate(lang, "check:Please register using the phone corresponding to the invitation code")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine whether the invitation code is in the form of a regular expression other than pure numbers and letters
|
// Determine whether the invitation code is in the form of a regular expression other than pure numbers and letters
|
||||||
if invitation.IsRegexp {
|
if invitation.IsRegexp {
|
||||||
@ -179,3 +219,19 @@ func (invitation *Invitation) IsInvitationCodeValid(application *Application, in
|
|||||||
}
|
}
|
||||||
return true, ""
|
return true, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (invitation *Invitation) IsInvitationCodeValid(application *Application, invitationCode string, username string, email string, phone string, lang string) (bool, string) {
|
||||||
|
if isValid, msg := invitation.SimpleCheckInvitationCode(invitationCode, lang); !isValid {
|
||||||
|
return false, msg
|
||||||
|
}
|
||||||
|
if application.IsSignupItemRequired("Username") && invitation.Username != "" && invitation.Username != username {
|
||||||
|
return false, i18n.Translate(lang, "check:Please register using the username corresponding to the invitation code")
|
||||||
|
}
|
||||||
|
if application.IsSignupItemRequired("Email") && invitation.Email != "" && invitation.Email != email {
|
||||||
|
return false, i18n.Translate(lang, "check:Please register using the email corresponding to the invitation code")
|
||||||
|
}
|
||||||
|
if application.IsSignupItemRequired("Phone") && invitation.Phone != "" && invitation.Phone != phone {
|
||||||
|
return false, i18n.Translate(lang, "check:Please register using the phone corresponding to the invitation code")
|
||||||
|
}
|
||||||
|
return true, ""
|
||||||
|
}
|
||||||
|
@ -94,6 +94,7 @@ func initAPI() {
|
|||||||
|
|
||||||
beego.Router("/api/get-invitations", &controllers.ApiController{}, "GET:GetInvitations")
|
beego.Router("/api/get-invitations", &controllers.ApiController{}, "GET:GetInvitations")
|
||||||
beego.Router("/api/get-invitation", &controllers.ApiController{}, "GET:GetInvitation")
|
beego.Router("/api/get-invitation", &controllers.ApiController{}, "GET:GetInvitation")
|
||||||
|
beego.Router("/api/get-invitation-info", &controllers.ApiController{}, "GET:GetInvitationCodeInfo")
|
||||||
beego.Router("/api/update-invitation", &controllers.ApiController{}, "POST:UpdateInvitation")
|
beego.Router("/api/update-invitation", &controllers.ApiController{}, "POST:UpdateInvitation")
|
||||||
beego.Router("/api/add-invitation", &controllers.ApiController{}, "POST:AddInvitation")
|
beego.Router("/api/add-invitation", &controllers.ApiController{}, "POST:AddInvitation")
|
||||||
beego.Router("/api/delete-invitation", &controllers.ApiController{}, "POST:DeleteInvitation")
|
beego.Router("/api/delete-invitation", &controllers.ApiController{}, "POST:DeleteInvitation")
|
||||||
|
@ -19,6 +19,7 @@ import * as OrganizationBackend from "./backend/OrganizationBackend";
|
|||||||
import * as ApplicationBackend from "./backend/ApplicationBackend";
|
import * as ApplicationBackend from "./backend/ApplicationBackend";
|
||||||
import * as Setting from "./Setting";
|
import * as Setting from "./Setting";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
import copy from "copy-to-clipboard";
|
||||||
|
|
||||||
const {Option} = Select;
|
const {Option} = Select;
|
||||||
|
|
||||||
@ -99,6 +100,18 @@ class InvitationEditPage extends React.Component {
|
|||||||
{this.state.mode === "add" ? i18next.t("invitation:New Invitation") : i18next.t("invitation:Edit Invitation")}
|
{this.state.mode === "add" ? i18next.t("invitation:New Invitation") : i18next.t("invitation:Edit Invitation")}
|
||||||
<Button onClick={() => this.submitInvitationEdit(false)}>{i18next.t("general:Save")}</Button>
|
<Button onClick={() => this.submitInvitationEdit(false)}>{i18next.t("general:Save")}</Button>
|
||||||
<Button style={{marginLeft: "20px"}} type="primary" onClick={() => this.submitInvitationEdit(true)}>{i18next.t("general:Save & Exit")}</Button>
|
<Button style={{marginLeft: "20px"}} type="primary" onClick={() => this.submitInvitationEdit(true)}>{i18next.t("general:Save & Exit")}</Button>
|
||||||
|
<Button style={{marginLeft: "20px"}} onClick={() => {
|
||||||
|
let defaultApplication;
|
||||||
|
if (this.state.invitation.owner === "built-in") {
|
||||||
|
defaultApplication = "app-built-in";
|
||||||
|
} else {
|
||||||
|
defaultApplication = Setting.getArrayItem(this.state.organizations, "name", this.state.invitation.owner).defaultApplication;
|
||||||
|
}
|
||||||
|
copy(`${window.location.origin}/signup/${defaultApplication}?invitationCode=${this.state.invitation?.defaultCode}`);
|
||||||
|
Setting.showMessage("success", i18next.t("general:Copied to clipboard successfully"));
|
||||||
|
}}>
|
||||||
|
{i18next.t("application:Copy signup page URL")}
|
||||||
|
</Button>
|
||||||
{this.state.mode === "add" ? <Button style={{marginLeft: "20px"}} onClick={() => this.deleteInvitation()}>{i18next.t("general:Cancel")}</Button> : null}
|
{this.state.mode === "add" ? <Button style={{marginLeft: "20px"}} onClick={() => this.deleteInvitation()}>{i18next.t("general:Cancel")}</Button> : null}
|
||||||
</div>
|
</div>
|
||||||
} style={(Setting.isMobile()) ? {margin: "5px"} : {}} type="inner">
|
} style={(Setting.isMobile()) ? {margin: "5px"} : {}} type="inner">
|
||||||
@ -140,10 +153,24 @@ class InvitationEditPage extends React.Component {
|
|||||||
</Col>
|
</Col>
|
||||||
<Col span={22} >
|
<Col span={22} >
|
||||||
<Input value={this.state.invitation.code} onChange={e => {
|
<Input value={this.state.invitation.code} onChange={e => {
|
||||||
|
const regex = /[^a-zA-Z0-9]/;
|
||||||
|
if (!regex.test(e.target.value)) {
|
||||||
|
this.updateInvitationField("defaultCode", e.target.value);
|
||||||
|
}
|
||||||
this.updateInvitationField("code", e.target.value);
|
this.updateInvitationField("code", e.target.value);
|
||||||
}} />
|
}} />
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
<Row style={{marginTop: "20px"}} >
|
||||||
|
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||||
|
{Setting.getLabel(i18next.t("invitation:Default code"), i18next.t("invitation:Default code - Tooltip"))} :
|
||||||
|
</Col>
|
||||||
|
<Col span={22} >
|
||||||
|
<Input value={this.state.invitation.defaultCode} onChange={e => {
|
||||||
|
this.updateInvitationField("defaultCode", e.target.value);
|
||||||
|
}} />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
<Row style={{marginTop: "20px"}} >
|
<Row style={{marginTop: "20px"}} >
|
||||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||||
{Setting.getLabel(i18next.t("invitation:Quota"), i18next.t("invitation:Quota - Tooltip"))} :
|
{Setting.getLabel(i18next.t("invitation:Quota"), i18next.t("invitation:Quota - Tooltip"))} :
|
||||||
@ -274,6 +301,18 @@ class InvitationEditPage extends React.Component {
|
|||||||
<div style={{marginTop: "20px", marginLeft: "40px"}}>
|
<div style={{marginTop: "20px", marginLeft: "40px"}}>
|
||||||
<Button size="large" onClick={() => this.submitInvitationEdit(false)}>{i18next.t("general:Save")}</Button>
|
<Button size="large" onClick={() => this.submitInvitationEdit(false)}>{i18next.t("general:Save")}</Button>
|
||||||
<Button style={{marginLeft: "20px"}} type="primary" size="large" onClick={() => this.submitInvitationEdit(true)}>{i18next.t("general:Save & Exit")}</Button>
|
<Button style={{marginLeft: "20px"}} type="primary" size="large" onClick={() => this.submitInvitationEdit(true)}>{i18next.t("general:Save & Exit")}</Button>
|
||||||
|
<Button style={{marginLeft: "20px"}} size="large" onClick={() => {
|
||||||
|
let defaultApplication;
|
||||||
|
if (this.state.invitation.owner === "built-in") {
|
||||||
|
defaultApplication = "app-built-in";
|
||||||
|
} else {
|
||||||
|
defaultApplication = Setting.getArrayItem(this.state.organizations, "name", this.state.invitation.owner).defaultApplication;
|
||||||
|
}
|
||||||
|
copy(`${window.location.origin}/signup/${defaultApplication}?invitationCode=${this.state.invitation?.defaultCode}`);
|
||||||
|
Setting.showMessage("success", i18next.t("general:Copied to clipboard successfully"));
|
||||||
|
}}>
|
||||||
|
{i18next.t("application:Copy signup page URL")}
|
||||||
|
</Button>
|
||||||
{this.state.mode === "add" ? <Button style={{marginLeft: "20px"}} size="large" onClick={() => this.deleteInvitation()}>{i18next.t("general:Cancel")}</Button> : null}
|
{this.state.mode === "add" ? <Button style={{marginLeft: "20px"}} size="large" onClick={() => this.deleteInvitation()}>{i18next.t("general:Cancel")}</Button> : null}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -22,19 +22,20 @@ import * as InvitationBackend from "./backend/InvitationBackend";
|
|||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import BaseListPage from "./BaseListPage";
|
import BaseListPage from "./BaseListPage";
|
||||||
import PopconfirmModal from "./common/modal/PopconfirmModal";
|
import PopconfirmModal from "./common/modal/PopconfirmModal";
|
||||||
import copy from "copy-to-clipboard";
|
|
||||||
|
|
||||||
class InvitationListPage extends BaseListPage {
|
class InvitationListPage extends BaseListPage {
|
||||||
newInvitation() {
|
newInvitation() {
|
||||||
const randomName = Setting.getRandomName();
|
const randomName = Setting.getRandomName();
|
||||||
const owner = Setting.getRequestOrganization(this.props.account);
|
const owner = Setting.getRequestOrganization(this.props.account);
|
||||||
|
const code = Math.random().toString(36).slice(-10);
|
||||||
return {
|
return {
|
||||||
owner: owner,
|
owner: owner,
|
||||||
name: `invitation_${randomName}`,
|
name: `invitation_${randomName}`,
|
||||||
createdTime: moment().format(),
|
createdTime: moment().format(),
|
||||||
updatedTime: moment().format(),
|
updatedTime: moment().format(),
|
||||||
displayName: `New Invitation - ${randomName}`,
|
displayName: `New Invitation - ${randomName}`,
|
||||||
code: Math.random().toString(36).slice(-10),
|
code: code,
|
||||||
|
defaultCode: code,
|
||||||
quota: 1,
|
quota: 1,
|
||||||
usedCount: 0,
|
usedCount: 0,
|
||||||
application: "All",
|
application: "All",
|
||||||
@ -225,17 +226,11 @@ class InvitationListPage extends BaseListPage {
|
|||||||
title: i18next.t("general:Action"),
|
title: i18next.t("general:Action"),
|
||||||
dataIndex: "",
|
dataIndex: "",
|
||||||
key: "op",
|
key: "op",
|
||||||
width: "350px",
|
width: "180px",
|
||||||
fixed: (Setting.isMobile()) ? "false" : "right",
|
fixed: (Setting.isMobile()) ? "false" : "right",
|
||||||
render: (text, record, index) => {
|
render: (text, record, index) => {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} onClick={() => {
|
|
||||||
copy(`${window.location.origin}/login/${record.owner}?invitation_code=${record.code}`);
|
|
||||||
Setting.showMessage("success", i18next.t("general:Copied to clipboard successfully"));
|
|
||||||
}}>
|
|
||||||
{i18next.t("application:Copy signup page URL")}
|
|
||||||
</Button>
|
|
||||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary" onClick={() => this.props.history.push(`/invitations/${record.owner}/${record.name}`)}>{i18next.t("general:Edit")}</Button>
|
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary" onClick={() => this.props.history.push(`/invitations/${record.owner}/${record.name}`)}>{i18next.t("general:Edit")}</Button>
|
||||||
<PopconfirmModal
|
<PopconfirmModal
|
||||||
title={i18next.t("general:Sure to delete") + `: ${record.name} ?`}
|
title={i18next.t("general:Sure to delete") + `: ${record.name} ?`}
|
||||||
|
@ -29,6 +29,7 @@ import LanguageSelect from "../common/select/LanguageSelect";
|
|||||||
import {withRouter} from "react-router-dom";
|
import {withRouter} from "react-router-dom";
|
||||||
import {CountryCodeSelect} from "../common/select/CountryCodeSelect";
|
import {CountryCodeSelect} from "../common/select/CountryCodeSelect";
|
||||||
import * as PasswordChecker from "../common/PasswordChecker";
|
import * as PasswordChecker from "../common/PasswordChecker";
|
||||||
|
import * as InvitationBackend from "../backend/InvitationBackend";
|
||||||
|
|
||||||
const formItemLayout = {
|
const formItemLayout = {
|
||||||
labelCol: {
|
labelCol: {
|
||||||
@ -93,6 +94,15 @@ class SignupPage extends React.Component {
|
|||||||
if (this.getApplicationObj() === undefined) {
|
if (this.getApplicationObj() === undefined) {
|
||||||
if (this.state.applicationName !== null) {
|
if (this.state.applicationName !== null) {
|
||||||
this.getApplication(this.state.applicationName);
|
this.getApplication(this.state.applicationName);
|
||||||
|
|
||||||
|
const sp = new URLSearchParams(window.location.search);
|
||||||
|
if (sp.has("invitationCode")) {
|
||||||
|
const invitationCode = sp.get("invitationCode");
|
||||||
|
this.setState({invitationCode: invitationCode});
|
||||||
|
if (invitationCode !== "") {
|
||||||
|
this.getInvitationCodeInfo(invitationCode, "admin/" + this.state.applicationName);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (oAuthParams !== null) {
|
} else if (oAuthParams !== null) {
|
||||||
this.getApplicationLogin(oAuthParams);
|
this.getApplicationLogin(oAuthParams);
|
||||||
} else {
|
} else {
|
||||||
@ -133,6 +143,17 @@ class SignupPage extends React.Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getInvitationCodeInfo(invitationCode, application) {
|
||||||
|
InvitationBackend.getInvitationCodeInfo(invitationCode, application)
|
||||||
|
.then((res) => {
|
||||||
|
if (res.status === "error") {
|
||||||
|
Setting.showMessage("error", res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.setState({invitation: res.data});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
getResultPath(application, signupParams) {
|
getResultPath(application, signupParams) {
|
||||||
if (signupParams?.plan && signupParams?.pricing) {
|
if (signupParams?.plan && signupParams?.pricing) {
|
||||||
// the prompt page needs the user to be signed in, so for paid-user sign up, just go to buy-plan page
|
// the prompt page needs the user to be signed in, so for paid-user sign up, just go to buy-plan page
|
||||||
@ -235,7 +256,7 @@ class SignupPage extends React.Component {
|
|||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<Input placeholder={signupItem.placeholder} />
|
<Input placeholder={signupItem.placeholder} disabled={this.state.invitation !== undefined && this.state.invitation.username !== ""} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
);
|
);
|
||||||
} else if (signupItem.name === "Display name") {
|
} else if (signupItem.name === "Display name") {
|
||||||
@ -363,7 +384,7 @@ class SignupPage extends React.Component {
|
|||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<Input placeholder={signupItem.placeholder} onChange={e => this.setState({email: e.target.value})} />
|
<Input placeholder={signupItem.placeholder} disabled={this.state.invitation !== undefined && this.state.invitation.email !== ""} onChange={e => this.setState({email: e.target.value})} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
{
|
{
|
||||||
signupItem.rule !== "No verification" &&
|
signupItem.rule !== "No verification" &&
|
||||||
@ -434,6 +455,7 @@ class SignupPage extends React.Component {
|
|||||||
<Input
|
<Input
|
||||||
placeholder={signupItem.placeholder}
|
placeholder={signupItem.placeholder}
|
||||||
style={{width: "65%"}}
|
style={{width: "65%"}}
|
||||||
|
disabled={this.state.invitation !== undefined && this.state.invitation.phone !== ""}
|
||||||
onChange={e => this.setState({phone: e.target.value})}
|
onChange={e => this.setState({phone: e.target.value})}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
@ -524,7 +546,7 @@ class SignupPage extends React.Component {
|
|||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<Input placeholder={signupItem.placeholder} />
|
<Input placeholder={signupItem.placeholder} disabled={this.state.invitation !== undefined && this.state.invitation !== ""} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
);
|
);
|
||||||
} else if (signupItem.name === "Agreement") {
|
} else if (signupItem.name === "Agreement") {
|
||||||
@ -554,6 +576,20 @@ class SignupPage extends React.Component {
|
|||||||
</Result>
|
</Result>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (this.state.invitation !== undefined) {
|
||||||
|
if (this.state.invitation.username !== "") {
|
||||||
|
this.form.current?.setFieldValue("username", this.state.invitation.username);
|
||||||
|
}
|
||||||
|
if (this.state.invitation.email !== "") {
|
||||||
|
this.form.current?.setFieldValue("email", this.state.invitation.email);
|
||||||
|
}
|
||||||
|
if (this.state.invitation.phone !== "") {
|
||||||
|
this.form.current?.setFieldValue("phone", this.state.invitation.phone);
|
||||||
|
}
|
||||||
|
if (this.state.invitationCode !== "") {
|
||||||
|
this.form.current?.setFieldValue("invitationCode", this.state.invitationCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<Form
|
<Form
|
||||||
{...formItemLayout}
|
{...formItemLayout}
|
||||||
|
@ -34,6 +34,16 @@ export function getInvitation(owner, name) {
|
|||||||
}).then(res => res.json());
|
}).then(res => res.json());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getInvitationCodeInfo(code, applicationName) {
|
||||||
|
return fetch(`${Setting.ServerUrl}/api/get-invitation-info?code=${code}&applicationId=${encodeURIComponent(applicationName)}`, {
|
||||||
|
method: "GET",
|
||||||
|
credentials: "include",
|
||||||
|
headers: {
|
||||||
|
"Accept-Language": Setting.getAcceptLanguage(),
|
||||||
|
},
|
||||||
|
}).then(res => res.json());
|
||||||
|
}
|
||||||
|
|
||||||
export function updateInvitation(owner, name, invitation) {
|
export function updateInvitation(owner, name, invitation) {
|
||||||
const newInvitation = Setting.deepCopy(invitation);
|
const newInvitation = Setting.deepCopy(invitation);
|
||||||
return fetch(`${Setting.ServerUrl}/api/update-invitation?id=${owner}/${encodeURIComponent(name)}`, {
|
return fetch(`${Setting.ServerUrl}/api/update-invitation?id=${owner}/${encodeURIComponent(name)}`, {
|
||||||
|
@ -388,6 +388,8 @@
|
|||||||
"invitation": {
|
"invitation": {
|
||||||
"Code": "Code",
|
"Code": "Code",
|
||||||
"Code - Tooltip": "Code - Tooltip",
|
"Code - Tooltip": "Code - Tooltip",
|
||||||
|
"Default code": "Default code",
|
||||||
|
"Default code - Tooltip": "When the invitation code is a regular expression, please enter the invitation code that matches the regular expression rule as the default invitation code for the invitation link",
|
||||||
"Edit Invitation": "Edit Invitation",
|
"Edit Invitation": "Edit Invitation",
|
||||||
"New Invitation": "New Invitation",
|
"New Invitation": "New Invitation",
|
||||||
"Quota": "Quota",
|
"Quota": "Quota",
|
||||||
|
@ -388,6 +388,8 @@
|
|||||||
"invitation": {
|
"invitation": {
|
||||||
"Code": "Code",
|
"Code": "Code",
|
||||||
"Code - Tooltip": "Code - Tooltip",
|
"Code - Tooltip": "Code - Tooltip",
|
||||||
|
"Default code": "Default code",
|
||||||
|
"Default code - Tooltip": "When the invitation code is a regular expression, please enter the invitation code that matches the regular expression rule as the default invitation code for the invitation link",
|
||||||
"Edit Invitation": "Edit Invitation",
|
"Edit Invitation": "Edit Invitation",
|
||||||
"New Invitation": "New Invitation",
|
"New Invitation": "New Invitation",
|
||||||
"Quota": "Quota",
|
"Quota": "Quota",
|
||||||
|
@ -390,6 +390,8 @@
|
|||||||
"invitation": {
|
"invitation": {
|
||||||
"Code": "Code",
|
"Code": "Code",
|
||||||
"Code - Tooltip": "Can be a single string as an invitation code, or a regular expression. All strings matching the regular expression are valid invitation codes",
|
"Code - Tooltip": "Can be a single string as an invitation code, or a regular expression. All strings matching the regular expression are valid invitation codes",
|
||||||
|
"Default code": "Default code",
|
||||||
|
"Default code - Tooltip": "When the invitation code is a regular expression, please enter the invitation code that matches the regular expression rule as the default invitation code for the invitation link",
|
||||||
"Edit Invitation": "Edit Invitation",
|
"Edit Invitation": "Edit Invitation",
|
||||||
"New Invitation": "New Invitation",
|
"New Invitation": "New Invitation",
|
||||||
"Quota": "Quota",
|
"Quota": "Quota",
|
||||||
|
@ -388,6 +388,8 @@
|
|||||||
"invitation": {
|
"invitation": {
|
||||||
"Code": "Code",
|
"Code": "Code",
|
||||||
"Code - Tooltip": "Code - Tooltip",
|
"Code - Tooltip": "Code - Tooltip",
|
||||||
|
"Default code": "Default code",
|
||||||
|
"Default code - Tooltip": "When the invitation code is a regular expression, please enter the invitation code that matches the regular expression rule as the default invitation code for the invitation link",
|
||||||
"Edit Invitation": "Edit Invitation",
|
"Edit Invitation": "Edit Invitation",
|
||||||
"New Invitation": "New Invitation",
|
"New Invitation": "New Invitation",
|
||||||
"Quota": "Quota",
|
"Quota": "Quota",
|
||||||
|
@ -388,6 +388,8 @@
|
|||||||
"invitation": {
|
"invitation": {
|
||||||
"Code": "Code",
|
"Code": "Code",
|
||||||
"Code - Tooltip": "Code - Tooltip",
|
"Code - Tooltip": "Code - Tooltip",
|
||||||
|
"Default code": "Default code",
|
||||||
|
"Default code - Tooltip": "When the invitation code is a regular expression, please enter the invitation code that matches the regular expression rule as the default invitation code for the invitation link",
|
||||||
"Edit Invitation": "Edit Invitation",
|
"Edit Invitation": "Edit Invitation",
|
||||||
"New Invitation": "New Invitation",
|
"New Invitation": "New Invitation",
|
||||||
"Quota": "Quota",
|
"Quota": "Quota",
|
||||||
|
@ -388,6 +388,8 @@
|
|||||||
"invitation": {
|
"invitation": {
|
||||||
"Code": "Code",
|
"Code": "Code",
|
||||||
"Code - Tooltip": "Code - Tooltip",
|
"Code - Tooltip": "Code - Tooltip",
|
||||||
|
"Default code": "Default code",
|
||||||
|
"Default code - Tooltip": "When the invitation code is a regular expression, please enter the invitation code that matches the regular expression rule as the default invitation code for the invitation link",
|
||||||
"Edit Invitation": "Edit Invitation",
|
"Edit Invitation": "Edit Invitation",
|
||||||
"New Invitation": "New Invitation",
|
"New Invitation": "New Invitation",
|
||||||
"Quota": "Quota",
|
"Quota": "Quota",
|
||||||
|
@ -388,6 +388,8 @@
|
|||||||
"invitation": {
|
"invitation": {
|
||||||
"Code": "Code",
|
"Code": "Code",
|
||||||
"Code - Tooltip": "Code - Tooltip",
|
"Code - Tooltip": "Code - Tooltip",
|
||||||
|
"Default code": "Default code",
|
||||||
|
"Default code - Tooltip": "When the invitation code is a regular expression, please enter the invitation code that matches the regular expression rule as the default invitation code for the invitation link",
|
||||||
"Edit Invitation": "Edit Invitation",
|
"Edit Invitation": "Edit Invitation",
|
||||||
"New Invitation": "New Invitation",
|
"New Invitation": "New Invitation",
|
||||||
"Quota": "Quota",
|
"Quota": "Quota",
|
||||||
|
@ -388,6 +388,8 @@
|
|||||||
"invitation": {
|
"invitation": {
|
||||||
"Code": "Code",
|
"Code": "Code",
|
||||||
"Code - Tooltip": "Code - Tooltip",
|
"Code - Tooltip": "Code - Tooltip",
|
||||||
|
"Default code": "Default code",
|
||||||
|
"Default code - Tooltip": "When the invitation code is a regular expression, please enter the invitation code that matches the regular expression rule as the default invitation code for the invitation link",
|
||||||
"Edit Invitation": "Edit Invitation",
|
"Edit Invitation": "Edit Invitation",
|
||||||
"New Invitation": "New Invitation",
|
"New Invitation": "New Invitation",
|
||||||
"Quota": "Quota",
|
"Quota": "Quota",
|
||||||
|
@ -388,6 +388,8 @@
|
|||||||
"invitation": {
|
"invitation": {
|
||||||
"Code": "Code",
|
"Code": "Code",
|
||||||
"Code - Tooltip": "Code - Tooltip",
|
"Code - Tooltip": "Code - Tooltip",
|
||||||
|
"Default code": "Default code",
|
||||||
|
"Default code - Tooltip": "When the invitation code is a regular expression, please enter the invitation code that matches the regular expression rule as the default invitation code for the invitation link",
|
||||||
"Edit Invitation": "Edit Invitation",
|
"Edit Invitation": "Edit Invitation",
|
||||||
"New Invitation": "New Invitation",
|
"New Invitation": "New Invitation",
|
||||||
"Quota": "Quota",
|
"Quota": "Quota",
|
||||||
|
@ -388,6 +388,8 @@
|
|||||||
"invitation": {
|
"invitation": {
|
||||||
"Code": "Code",
|
"Code": "Code",
|
||||||
"Code - Tooltip": "Code - Tooltip",
|
"Code - Tooltip": "Code - Tooltip",
|
||||||
|
"Default code": "Default code",
|
||||||
|
"Default code - Tooltip": "When the invitation code is a regular expression, please enter the invitation code that matches the regular expression rule as the default invitation code for the invitation link",
|
||||||
"Edit Invitation": "Edit Invitation",
|
"Edit Invitation": "Edit Invitation",
|
||||||
"New Invitation": "New Invitation",
|
"New Invitation": "New Invitation",
|
||||||
"Quota": "Quota",
|
"Quota": "Quota",
|
||||||
|
@ -388,6 +388,8 @@
|
|||||||
"invitation": {
|
"invitation": {
|
||||||
"Code": "Code",
|
"Code": "Code",
|
||||||
"Code - Tooltip": "Code - Tooltip",
|
"Code - Tooltip": "Code - Tooltip",
|
||||||
|
"Default code": "Default code",
|
||||||
|
"Default code - Tooltip": "When the invitation code is a regular expression, please enter the invitation code that matches the regular expression rule as the default invitation code for the invitation link",
|
||||||
"Edit Invitation": "Edit Invitation",
|
"Edit Invitation": "Edit Invitation",
|
||||||
"New Invitation": "New Invitation",
|
"New Invitation": "New Invitation",
|
||||||
"Quota": "Quota",
|
"Quota": "Quota",
|
||||||
|
@ -388,6 +388,8 @@
|
|||||||
"invitation": {
|
"invitation": {
|
||||||
"Code": "Code",
|
"Code": "Code",
|
||||||
"Code - Tooltip": "Code - Tooltip",
|
"Code - Tooltip": "Code - Tooltip",
|
||||||
|
"Default code": "Default code",
|
||||||
|
"Default code - Tooltip": "When the invitation code is a regular expression, please enter the invitation code that matches the regular expression rule as the default invitation code for the invitation link",
|
||||||
"Edit Invitation": "Edit Invitation",
|
"Edit Invitation": "Edit Invitation",
|
||||||
"New Invitation": "New Invitation",
|
"New Invitation": "New Invitation",
|
||||||
"Quota": "Quota",
|
"Quota": "Quota",
|
||||||
|
@ -388,6 +388,8 @@
|
|||||||
"invitation": {
|
"invitation": {
|
||||||
"Code": "Code",
|
"Code": "Code",
|
||||||
"Code - Tooltip": "Code - Tooltip",
|
"Code - Tooltip": "Code - Tooltip",
|
||||||
|
"Default code": "Default code",
|
||||||
|
"Default code - Tooltip": "When the invitation code is a regular expression, please enter the invitation code that matches the regular expression rule as the default invitation code for the invitation link",
|
||||||
"Edit Invitation": "Edit Invitation",
|
"Edit Invitation": "Edit Invitation",
|
||||||
"New Invitation": "New Invitation",
|
"New Invitation": "New Invitation",
|
||||||
"Quota": "Quota",
|
"Quota": "Quota",
|
||||||
|
@ -388,6 +388,8 @@
|
|||||||
"invitation": {
|
"invitation": {
|
||||||
"Code": "Code",
|
"Code": "Code",
|
||||||
"Code - Tooltip": "Code - Tooltip",
|
"Code - Tooltip": "Code - Tooltip",
|
||||||
|
"Default code": "Default code",
|
||||||
|
"Default code - Tooltip": "When the invitation code is a regular expression, please enter the invitation code that matches the regular expression rule as the default invitation code for the invitation link",
|
||||||
"Edit Invitation": "Edit Invitation",
|
"Edit Invitation": "Edit Invitation",
|
||||||
"New Invitation": "New Invitation",
|
"New Invitation": "New Invitation",
|
||||||
"Quota": "Quota",
|
"Quota": "Quota",
|
||||||
|
@ -388,6 +388,8 @@
|
|||||||
"invitation": {
|
"invitation": {
|
||||||
"Code": "Code",
|
"Code": "Code",
|
||||||
"Code - Tooltip": "Code - Tooltip",
|
"Code - Tooltip": "Code - Tooltip",
|
||||||
|
"Default code": "Default code",
|
||||||
|
"Default code - Tooltip": "When the invitation code is a regular expression, please enter the invitation code that matches the regular expression rule as the default invitation code for the invitation link",
|
||||||
"Edit Invitation": "Edit Invitation",
|
"Edit Invitation": "Edit Invitation",
|
||||||
"New Invitation": "New Invitation",
|
"New Invitation": "New Invitation",
|
||||||
"Quota": "Quota",
|
"Quota": "Quota",
|
||||||
|
@ -388,6 +388,8 @@
|
|||||||
"invitation": {
|
"invitation": {
|
||||||
"Code": "Code",
|
"Code": "Code",
|
||||||
"Code - Tooltip": "Code - Tooltip",
|
"Code - Tooltip": "Code - Tooltip",
|
||||||
|
"Default code": "Default code",
|
||||||
|
"Default code - Tooltip": "When the invitation code is a regular expression, please enter the invitation code that matches the regular expression rule as the default invitation code for the invitation link",
|
||||||
"Edit Invitation": "Edit Invitation",
|
"Edit Invitation": "Edit Invitation",
|
||||||
"New Invitation": "New Invitation",
|
"New Invitation": "New Invitation",
|
||||||
"Quota": "Quota",
|
"Quota": "Quota",
|
||||||
|
@ -388,6 +388,8 @@
|
|||||||
"invitation": {
|
"invitation": {
|
||||||
"Code": "Code",
|
"Code": "Code",
|
||||||
"Code - Tooltip": "Code - Tooltip",
|
"Code - Tooltip": "Code - Tooltip",
|
||||||
|
"Default code": "Default code",
|
||||||
|
"Default code - Tooltip": "When the invitation code is a regular expression, please enter the invitation code that matches the regular expression rule as the default invitation code for the invitation link",
|
||||||
"Edit Invitation": "Edit Invitation",
|
"Edit Invitation": "Edit Invitation",
|
||||||
"New Invitation": "New Invitation",
|
"New Invitation": "New Invitation",
|
||||||
"Quota": "Quota",
|
"Quota": "Quota",
|
||||||
|
@ -388,6 +388,8 @@
|
|||||||
"invitation": {
|
"invitation": {
|
||||||
"Code": "Code",
|
"Code": "Code",
|
||||||
"Code - Tooltip": "Code - Tooltip",
|
"Code - Tooltip": "Code - Tooltip",
|
||||||
|
"Default code": "Default code",
|
||||||
|
"Default code - Tooltip": "When the invitation code is a regular expression, please enter the invitation code that matches the regular expression rule as the default invitation code for the invitation link",
|
||||||
"Edit Invitation": "Edit Invitation",
|
"Edit Invitation": "Edit Invitation",
|
||||||
"New Invitation": "New Invitation",
|
"New Invitation": "New Invitation",
|
||||||
"Quota": "Quota",
|
"Quota": "Quota",
|
||||||
|
@ -388,6 +388,8 @@
|
|||||||
"invitation": {
|
"invitation": {
|
||||||
"Code": "Code",
|
"Code": "Code",
|
||||||
"Code - Tooltip": "Code - Tooltip",
|
"Code - Tooltip": "Code - Tooltip",
|
||||||
|
"Default code": "Default code",
|
||||||
|
"Default code - Tooltip": "When the invitation code is a regular expression, please enter the invitation code that matches the regular expression rule as the default invitation code for the invitation link",
|
||||||
"Edit Invitation": "Edit Invitation",
|
"Edit Invitation": "Edit Invitation",
|
||||||
"New Invitation": "New Invitation",
|
"New Invitation": "New Invitation",
|
||||||
"Quota": "Quota",
|
"Quota": "Quota",
|
||||||
|
@ -388,6 +388,8 @@
|
|||||||
"invitation": {
|
"invitation": {
|
||||||
"Code": "Code",
|
"Code": "Code",
|
||||||
"Code - Tooltip": "Code - Tooltip",
|
"Code - Tooltip": "Code - Tooltip",
|
||||||
|
"Default code": "Default code",
|
||||||
|
"Default code - Tooltip": "When the invitation code is a regular expression, please enter the invitation code that matches the regular expression rule as the default invitation code for the invitation link",
|
||||||
"Edit Invitation": "Edit Invitation",
|
"Edit Invitation": "Edit Invitation",
|
||||||
"New Invitation": "New Invitation",
|
"New Invitation": "New Invitation",
|
||||||
"Quota": "Quota",
|
"Quota": "Quota",
|
||||||
|
@ -388,6 +388,8 @@
|
|||||||
"invitation": {
|
"invitation": {
|
||||||
"Code": "Code",
|
"Code": "Code",
|
||||||
"Code - Tooltip": "Code - Tooltip",
|
"Code - Tooltip": "Code - Tooltip",
|
||||||
|
"Default code": "Default code",
|
||||||
|
"Default code - Tooltip": "When the invitation code is a regular expression, please enter the invitation code that matches the regular expression rule as the default invitation code for the invitation link",
|
||||||
"Edit Invitation": "Edit Invitation",
|
"Edit Invitation": "Edit Invitation",
|
||||||
"New Invitation": "New Invitation",
|
"New Invitation": "New Invitation",
|
||||||
"Quota": "Quota",
|
"Quota": "Quota",
|
||||||
|
@ -388,6 +388,8 @@
|
|||||||
"invitation": {
|
"invitation": {
|
||||||
"Code": "Code",
|
"Code": "Code",
|
||||||
"Code - Tooltip": "Code - Tooltip",
|
"Code - Tooltip": "Code - Tooltip",
|
||||||
|
"Default code": "Default code",
|
||||||
|
"Default code - Tooltip": "When the invitation code is a regular expression, please enter the invitation code that matches the regular expression rule as the default invitation code for the invitation link",
|
||||||
"Edit Invitation": "Edit Invitation",
|
"Edit Invitation": "Edit Invitation",
|
||||||
"New Invitation": "New Invitation",
|
"New Invitation": "New Invitation",
|
||||||
"Quota": "Quota",
|
"Quota": "Quota",
|
||||||
|
@ -390,6 +390,8 @@
|
|||||||
"invitation": {
|
"invitation": {
|
||||||
"Code": "邀请码",
|
"Code": "邀请码",
|
||||||
"Code - Tooltip": "可以是一个单独的字符串作为邀请码,也可以是正则表达式,所有符合正则表达式的字符串都是合法的邀请码",
|
"Code - Tooltip": "可以是一个单独的字符串作为邀请码,也可以是正则表达式,所有符合正则表达式的字符串都是合法的邀请码",
|
||||||
|
"Default code": "默认邀请码",
|
||||||
|
"Default code - Tooltip": "当邀请码为正则表达式时,请输入符合正则表达式规则的邀请码作为邀请链接的默认邀请码",
|
||||||
"Edit Invitation": "编辑邀请码",
|
"Edit Invitation": "编辑邀请码",
|
||||||
"New Invitation": "新建邀请码",
|
"New Invitation": "新建邀请码",
|
||||||
"Quota": "配额",
|
"Quota": "配额",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user