mirror of
https://github.com/casdoor/casdoor.git
synced 2025-05-23 02:35:49 +08:00
feat: improve cert edit page UI
This commit is contained in:
parent
e9b7d1266f
commit
5b151f4ec4
@ -163,6 +163,12 @@ func UpdateCert(id string, cert *Cert) (bool, error) {
|
|||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err := cert.populateContent()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
affected, err := ormer.Engine.ID(core.PK{owner, name}).AllCols().Update(cert)
|
affected, err := ormer.Engine.ID(core.PK{owner, name}).AllCols().Update(cert)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@ -172,10 +178,9 @@ func UpdateCert(id string, cert *Cert) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func AddCert(cert *Cert) (bool, error) {
|
func AddCert(cert *Cert) (bool, error) {
|
||||||
if cert.Certificate == "" || cert.PrivateKey == "" {
|
err := cert.populateContent()
|
||||||
certificate, privateKey := generateRsaKeys(cert.BitSize, cert.ExpireInYears, cert.Name, cert.Owner)
|
if err != nil {
|
||||||
cert.Certificate = certificate
|
return false, err
|
||||||
cert.PrivateKey = privateKey
|
|
||||||
}
|
}
|
||||||
|
|
||||||
affected, err := ormer.Engine.Insert(cert)
|
affected, err := ormer.Engine.Insert(cert)
|
||||||
@ -199,6 +204,20 @@ func (p *Cert) GetId() string {
|
|||||||
return fmt.Sprintf("%s/%s", p.Owner, p.Name)
|
return fmt.Sprintf("%s/%s", p.Owner, p.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Cert) populateContent() error {
|
||||||
|
if p.Certificate == "" || p.PrivateKey == "" {
|
||||||
|
certificate, privateKey, err := generateRsaKeys(p.BitSize, p.ExpireInYears, p.Name, p.Owner)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
p.Certificate = certificate
|
||||||
|
p.PrivateKey = privateKey
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func getCertByApplication(application *Application) (*Cert, error) {
|
func getCertByApplication(application *Application) (*Cert, error) {
|
||||||
if application.Cert != "" {
|
if application.Cert != "" {
|
||||||
return getCertByName(application.Cert)
|
return getCertByName(application.Cert)
|
||||||
|
@ -24,14 +24,14 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func generateRsaKeys(bitSize int, expireInYears int, commonName string, organization string) (string, string) {
|
func generateRsaKeys(bitSize int, expireInYears int, commonName string, organization string) (string, string, error) {
|
||||||
// https://stackoverflow.com/questions/64104586/use-golang-to-get-rsa-key-the-same-way-openssl-genrsa
|
// https://stackoverflow.com/questions/64104586/use-golang-to-get-rsa-key-the-same-way-openssl-genrsa
|
||||||
// https://stackoverflow.com/questions/43822945/golang-can-i-create-x509keypair-using-rsa-key
|
// https://stackoverflow.com/questions/43822945/golang-can-i-create-x509keypair-using-rsa-key
|
||||||
|
|
||||||
// Generate RSA key.
|
// Generate RSA key.
|
||||||
key, err := rsa.GenerateKey(rand.Reader, bitSize)
|
key, err := rsa.GenerateKey(rand.Reader, bitSize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return "", "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encode private key to PKCS#1 ASN.1 PEM.
|
// Encode private key to PKCS#1 ASN.1 PEM.
|
||||||
@ -54,9 +54,10 @@ func generateRsaKeys(bitSize int, expireInYears int, commonName string, organiza
|
|||||||
},
|
},
|
||||||
BasicConstraintsValid: true,
|
BasicConstraintsValid: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
cert, err := x509.CreateCertificate(rand.Reader, &tml, &tml, &key.PublicKey, key)
|
cert, err := x509.CreateCertificate(rand.Reader, &tml, &tml, &key.PublicKey, key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return "", "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate a pem block with the certificate
|
// Generate a pem block with the certificate
|
||||||
@ -65,5 +66,5 @@ func generateRsaKeys(bitSize int, expireInYears int, commonName string, organiza
|
|||||||
Bytes: cert,
|
Bytes: cert,
|
||||||
})
|
})
|
||||||
|
|
||||||
return string(certPem), string(privateKeyPem)
|
return string(certPem), string(privateKeyPem), nil
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,10 @@ import (
|
|||||||
|
|
||||||
func TestGenerateRsaKeys(t *testing.T) {
|
func TestGenerateRsaKeys(t *testing.T) {
|
||||||
fileId := "token_jwt_key"
|
fileId := "token_jwt_key"
|
||||||
certificate, privateKey := generateRsaKeys(4096, 20, "Casdoor Cert", "Casdoor Organization")
|
certificate, privateKey, err := generateRsaKeys(4096, 20, "Casdoor Cert", "Casdoor Organization")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
// Write certificate (aka certificate) to file.
|
// Write certificate (aka certificate) to file.
|
||||||
util.WriteStringToPath(certificate, fmt.Sprintf("%s.pem", fileId))
|
util.WriteStringToPath(certificate, fmt.Sprintf("%s.pem", fileId))
|
||||||
|
@ -171,10 +171,27 @@ class CertEditPage extends React.Component {
|
|||||||
<Col span={22} >
|
<Col span={22} >
|
||||||
<Select virtual={false} style={{width: "100%"}} value={this.state.cert.cryptoAlgorithm} onChange={(value => {
|
<Select virtual={false} style={{width: "100%"}} value={this.state.cert.cryptoAlgorithm} onChange={(value => {
|
||||||
this.updateCertField("cryptoAlgorithm", value);
|
this.updateCertField("cryptoAlgorithm", value);
|
||||||
|
if (value === "RS256") {
|
||||||
|
this.updateCertField("bitSize", 2048);
|
||||||
|
} else if (value === "HS256" || value === "ES256") {
|
||||||
|
this.updateCertField("bitSize", 256);
|
||||||
|
} else if (value === "ES384") {
|
||||||
|
this.updateCertField("bitSize", 384);
|
||||||
|
} else if (value === "ES521") {
|
||||||
|
this.updateCertField("bitSize", 521);
|
||||||
|
} else {
|
||||||
|
this.updateCertField("bitSize", 0);
|
||||||
|
}
|
||||||
|
this.updateCertField("certificate", "");
|
||||||
|
this.updateCertField("privateKey", "");
|
||||||
})}>
|
})}>
|
||||||
{
|
{
|
||||||
[
|
[
|
||||||
{id: "RS256", name: "RS256"},
|
{id: "RS256", name: "RS256 (RSA + SHA256)"},
|
||||||
|
{id: "HS256", name: "HS256 (HMAC + SHA256)"},
|
||||||
|
{id: "ES256", name: "ES256 (ECDSA using P-256 + SHA256)"},
|
||||||
|
{id: "ES384", name: "ES384 (ECDSA using P-384 + SHA256)"},
|
||||||
|
{id: "ES521", name: "ES521 (ECDSA using P-521 + SHA256)"},
|
||||||
].map((item, index) => <Option key={index} value={item.id}>{item.name}</Option>)
|
].map((item, index) => <Option key={index} value={item.id}>{item.name}</Option>)
|
||||||
}
|
}
|
||||||
</Select>
|
</Select>
|
||||||
@ -185,9 +202,15 @@ class CertEditPage extends React.Component {
|
|||||||
{Setting.getLabel(i18next.t("cert:Bit size"), i18next.t("cert:Bit size - Tooltip"))} :
|
{Setting.getLabel(i18next.t("cert:Bit size"), i18next.t("cert:Bit size - Tooltip"))} :
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={22} >
|
<Col span={22} >
|
||||||
<InputNumber value={this.state.cert.bitSize} onChange={value => {
|
<Select virtual={false} style={{width: "100%"}} value={this.state.cert.bitSize} onChange={(value => {
|
||||||
this.updateCertField("bitSize", value);
|
this.updateCertField("bitSize", value);
|
||||||
}} />
|
this.updateCertField("certificate", "");
|
||||||
|
this.updateCertField("privateKey", "");
|
||||||
|
})}>
|
||||||
|
{
|
||||||
|
Setting.getCryptoAlgorithmOptions(this.state.cert.cryptoAlgorithm).map((item, index) => <Option key={index} value={item.id}>{item.name}</Option>)
|
||||||
|
}
|
||||||
|
</Select>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
<Row style={{marginTop: "20px"}} >
|
<Row style={{marginTop: "20px"}} >
|
||||||
@ -205,14 +228,14 @@ class CertEditPage extends React.Component {
|
|||||||
{Setting.getLabel(i18next.t("cert:Certificate"), i18next.t("cert:Certificate - Tooltip"))} :
|
{Setting.getLabel(i18next.t("cert:Certificate"), i18next.t("cert:Certificate - Tooltip"))} :
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={editorWidth} >
|
<Col span={editorWidth} >
|
||||||
<Button style={{marginRight: "10px", marginBottom: "10px"}} onClick={() => {
|
<Button style={{marginRight: "10px", marginBottom: "10px"}} disabled={this.state.cert.certificate === ""} onClick={() => {
|
||||||
copy(this.state.cert.certificate);
|
copy(this.state.cert.certificate);
|
||||||
Setting.showMessage("success", i18next.t("cert:Certificate copied to clipboard successfully"));
|
Setting.showMessage("success", i18next.t("cert:Certificate copied to clipboard successfully"));
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{i18next.t("cert:Copy certificate")}
|
{i18next.t("cert:Copy certificate")}
|
||||||
</Button>
|
</Button>
|
||||||
<Button type="primary" onClick={() => {
|
<Button type="primary" disabled={this.state.cert.certificate === ""} onClick={() => {
|
||||||
const blob = new Blob([this.state.cert.certificate], {type: "text/plain;charset=utf-8"});
|
const blob = new Blob([this.state.cert.certificate], {type: "text/plain;charset=utf-8"});
|
||||||
FileSaver.saveAs(blob, "token_jwt_key.pem");
|
FileSaver.saveAs(blob, "token_jwt_key.pem");
|
||||||
}}
|
}}
|
||||||
@ -228,14 +251,14 @@ class CertEditPage extends React.Component {
|
|||||||
{Setting.getLabel(i18next.t("cert:Private key"), i18next.t("cert:Private key - Tooltip"))} :
|
{Setting.getLabel(i18next.t("cert:Private key"), i18next.t("cert:Private key - Tooltip"))} :
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={editorWidth} >
|
<Col span={editorWidth} >
|
||||||
<Button style={{marginRight: "10px", marginBottom: "10px"}} onClick={() => {
|
<Button style={{marginRight: "10px", marginBottom: "10px"}} disabled={this.state.cert.privateKey === ""} onClick={() => {
|
||||||
copy(this.state.cert.privateKey);
|
copy(this.state.cert.privateKey);
|
||||||
Setting.showMessage("success", i18next.t("cert:Private key copied to clipboard successfully"));
|
Setting.showMessage("success", i18next.t("cert:Private key copied to clipboard successfully"));
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{i18next.t("cert:Copy private key")}
|
{i18next.t("cert:Copy private key")}
|
||||||
</Button>
|
</Button>
|
||||||
<Button type="primary" onClick={() => {
|
<Button type="primary" disabled={this.state.cert.privateKey === ""} onClick={() => {
|
||||||
const blob = new Blob([this.state.cert.privateKey], {type: "text/plain;charset=utf-8"});
|
const blob = new Blob([this.state.cert.privateKey], {type: "text/plain;charset=utf-8"});
|
||||||
FileSaver.saveAs(blob, "token_jwt_key.key");
|
FileSaver.saveAs(blob, "token_jwt_key.key");
|
||||||
}}
|
}}
|
||||||
@ -265,6 +288,7 @@ class CertEditPage extends React.Component {
|
|||||||
this.props.history.push("/certs");
|
this.props.history.push("/certs");
|
||||||
} else {
|
} else {
|
||||||
this.props.history.push(`/certs/${this.state.cert.owner}/${this.state.cert.name}`);
|
this.props.history.push(`/certs/${this.state.cert.owner}/${this.state.cert.name}`);
|
||||||
|
this.getCert();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Setting.showMessage("error", `${i18next.t("general:Failed to save")}: ${res.msg}`);
|
Setting.showMessage("error", `${i18next.t("general:Failed to save")}: ${res.msg}`);
|
||||||
|
@ -1069,6 +1069,38 @@ export function getProviderTypeOptions(category) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getCryptoAlgorithmOptions(cryptoAlgorithm) {
|
||||||
|
if (cryptoAlgorithm === "RS256") {
|
||||||
|
return (
|
||||||
|
[
|
||||||
|
{id: 1024, name: "1024"},
|
||||||
|
{id: 2048, name: "2048"},
|
||||||
|
{id: 4096, name: "4096"},
|
||||||
|
]
|
||||||
|
);
|
||||||
|
} else if (cryptoAlgorithm === "HS256" || cryptoAlgorithm === "ES256") {
|
||||||
|
return (
|
||||||
|
[
|
||||||
|
{id: 256, name: "256"},
|
||||||
|
]
|
||||||
|
);
|
||||||
|
} else if (cryptoAlgorithm === "ES384") {
|
||||||
|
return (
|
||||||
|
[
|
||||||
|
{id: 384, name: "384"},
|
||||||
|
]
|
||||||
|
);
|
||||||
|
} else if (cryptoAlgorithm === "ES521") {
|
||||||
|
return (
|
||||||
|
[
|
||||||
|
{id: 521, name: "521"},
|
||||||
|
]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function renderLogo(application) {
|
export function renderLogo(application) {
|
||||||
if (application === null) {
|
if (application === null) {
|
||||||
return null;
|
return null;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user