diff --git a/controllers/application.go b/controllers/application.go
index eb27f8fd..a6976bac 100644
--- a/controllers/application.go
+++ b/controllers/application.go
@@ -44,6 +44,18 @@ func (c *ApiController) GetApplication() {
c.ServeJSON()
}
+// @Title GetDefaultApplication
+// @Description get the detail of the default application
+// @Param owner query string true "The owner of the application."
+// @Success 200 {object} object.Application The Response object
+// @router /get-default-application [get]
+func (c *ApiController) GetDefaultApplication() {
+ owner := c.Input().Get("owner")
+
+ c.Data["json"] = object.GetDefaultApplication(owner)
+ c.ServeJSON()
+}
+
// @Title UpdateApplication
// @Description update an application
// @Param id query string true "The id of the application"
diff --git a/controllers/provider.go b/controllers/provider.go
index 2acb4e4c..ff820587 100644
--- a/controllers/provider.go
+++ b/controllers/provider.go
@@ -32,6 +32,18 @@ func (c *ApiController) GetProviders() {
c.ServeJSON()
}
+// @Title GetDefaultProviders
+// @Description get default providers
+// @Param owner query string true "The owner of providers"
+// @Success 200 {array} object.Provider The Response object
+// @router /get-default-providers [get]
+func (c *ApiController) GetDefaultProviders() {
+ owner := c.Input().Get("owner")
+
+ c.Data["json"] = object.GetDefaultProviders(owner)
+ c.ServeJSON()
+}
+
// @Title GetProvider
// @Description get provider
// @Param id query string true "The id of the provider"
diff --git a/object/application.go b/object/application.go
index d0fa8c62..34f172d1 100644
--- a/object/application.go
+++ b/object/application.go
@@ -80,6 +80,22 @@ func getApplication(owner string, name string) *Application {
}
}
+func GetDefaultApplication(owner string) *Application {
+ name := "app-built-in"
+ application := Application{Owner: owner, Name: name}
+ existed, err := adapter.engine.Get(&application)
+ if err != nil {
+ panic(err)
+ }
+
+ if existed {
+ extendApplication(&application)
+ return &application
+ } else {
+ return nil
+ }
+}
+
func getApplicationByClientId(clientId string) *Application {
application := Application{}
existed, err := adapter.engine.Where("client_id=?", clientId).Get(&application)
diff --git a/object/provider.go b/object/provider.go
index 1897bc47..9630c696 100644
--- a/object/provider.go
+++ b/object/provider.go
@@ -15,6 +15,8 @@
package object
import (
+ "strings"
+
"github.com/casdoor/casdoor/util"
"xorm.io/core"
)
@@ -41,6 +43,17 @@ func GetProviders(owner string) []*Provider {
return providers
}
+func GetDefaultProviders(owner string) []*Provider {
+ providers := GetProviders(owner)
+ res := []*Provider{}
+ for _, provider := range providers {
+ if strings.Contains(provider.Name, "casdoor") {
+ res = append(res, provider)
+ }
+ }
+ return res
+}
+
func getProvider(owner string, name string) *Provider {
provider := Provider{Owner: owner, Name: name}
existed, err := adapter.engine.Get(&provider)
diff --git a/routers/router.go b/routers/router.go
index baa94c9e..fc2229a5 100644
--- a/routers/router.go
+++ b/routers/router.go
@@ -61,6 +61,7 @@ func initAPI() {
beego.Router("/api/upload-avatar", &controllers.ApiController{}, "POST:UploadAvatar")
beego.Router("/api/get-providers", &controllers.ApiController{}, "GET:GetProviders")
+ beego.Router("/api/get-default-providers", &controllers.ApiController{}, "GET:GetDefaultProviders")
beego.Router("/api/get-provider", &controllers.ApiController{}, "GET:GetProvider")
beego.Router("/api/update-provider", &controllers.ApiController{}, "POST:UpdateProvider")
beego.Router("/api/add-provider", &controllers.ApiController{}, "POST:AddProvider")
@@ -68,6 +69,7 @@ func initAPI() {
beego.Router("/api/get-applications", &controllers.ApiController{}, "GET:GetApplications")
beego.Router("/api/get-application", &controllers.ApiController{}, "GET:GetApplication")
+ beego.Router("/api/get-default-application", &controllers.ApiController{}, "GET:GetDefaultApplication")
beego.Router("/api/update-application", &controllers.ApiController{}, "POST:UpdateApplication")
beego.Router("/api/add-application", &controllers.ApiController{}, "POST:AddApplication")
beego.Router("/api/delete-application", &controllers.ApiController{}, "POST:DeleteApplication")
diff --git a/web/src/Setting.js b/web/src/Setting.js
index be94a2e8..49fe10d4 100644
--- a/web/src/Setting.js
+++ b/web/src/Setting.js
@@ -172,7 +172,8 @@ export function getClickable(text) {
)
}
-export function getIdpLogo(idp) {
+export function getProviderLogo(provider) {
+ const idp = provider.type.toLowerCase();
const url = `https://cdn.jsdelivr.net/gh/casbin/static/img/social_${idp}.png`;
return (
diff --git a/web/src/UserEditPage.js b/web/src/UserEditPage.js
index a2c29083..ab5be93c 100644
--- a/web/src/UserEditPage.js
+++ b/web/src/UserEditPage.js
@@ -21,6 +21,9 @@ import {LinkOutlined} from "@ant-design/icons";
import i18next from "i18next";
import CropperDiv from "./CropperDiv.js";
import * as AuthBackend from "./auth/AuthBackend";
+import * as ApplicationBackend from "./backend/ApplicationBackend";
+import * as ProviderBackend from "./backend/ProviderBackend";
+import * as Provider from "./auth/Provider";
const { Option } = Select;
@@ -32,13 +35,17 @@ class UserEditPage extends React.Component {
organizationName: props.organizationName !== undefined ? props.organizationName : props.match.params.organizationName,
userName: props.userName !== undefined ? props.userName : props.match.params.userName,
user: null,
+ application: null,
organizations: [],
+ providers: [],
};
}
UNSAFE_componentWillMount() {
this.getUser();
this.getOrganizations();
+ this.getDefaultApplication();
+ this.getDefaultProviders();
}
getUser() {
@@ -59,6 +66,24 @@ class UserEditPage extends React.Component {
});
}
+ getDefaultApplication() {
+ ApplicationBackend.getDefaultApplication("admin")
+ .then((application) => {
+ this.setState({
+ application: application,
+ });
+ });
+ }
+
+ getDefaultProviders() {
+ ProviderBackend.getDefaultProviders("admin")
+ .then((res) => {
+ this.setState({
+ providers: res,
+ });
+ });
+ }
+
parseUserField(key, value) {
// if ([].includes(key)) {
// value = Setting.myParseInt(value);
@@ -76,9 +101,6 @@ class UserEditPage extends React.Component {
});
}
- linkUser(providerType) {
- }
-
unlinkUser(providerType) {
const body = {
providerType: providerType,
@@ -95,48 +117,52 @@ class UserEditPage extends React.Component {
});
}
- getIdpLink(idp, username) {
- if (idp === "github") {
- return `https://github.com/${username}`;
- } else if (idp === "google") {
+ getProviderLink(provider, linkedValue) {
+ if (provider.type === "GitHub") {
+ return `https://github.com/${linkedValue}`;
+ } else if (provider.type === "Google") {
return "https://mail.google.com";
} else {
return "";
}
}
- renderIdp(idp) {
+ renderIdp(provider) {
+ const linkedValue = this.state.user[provider.type.toLowerCase()];
+
return (
{
- Setting.getIdpLogo(idp.toLowerCase())
+ Setting.getProviderLogo(provider)
}
{
- `${idp}:`
+ `${provider.type}:`
}
{
- this.state.user[idp.toLowerCase()] === "" ? (
+ linkedValue === "" ? (
"(empty)"
) : (
-
+
{
- this.state.user[idp.toLowerCase()]
+ linkedValue
}
)
}
{
- this.state.user[idp.toLowerCase()] === "" ? (
-
+ linkedValue === "" ? (
+
+
+
) : (
-
+
)
}
@@ -286,16 +312,7 @@ class UserEditPage extends React.Component {
{
- this.renderIdp("GitHub")
- }
- {
- this.renderIdp("Google")
- }
- {
- this.renderIdp("QQ")
- }
- {
- this.renderIdp("WeChat")
+ this.state.providers.map((provider, index) => this.renderIdp(provider))
}
{
!Setting.isAdminUser(this.props.account) ? null : (
diff --git a/web/src/auth/AuthBackend.js b/web/src/auth/AuthBackend.js
index 1987b563..4d783ba7 100644
--- a/web/src/auth/AuthBackend.js
+++ b/web/src/auth/AuthBackend.js
@@ -63,10 +63,3 @@ export function unlink(values) {
body: JSON.stringify(values),
}).then(res => res.json());
}
-
-export function getApplication(owner, name) {
- return fetch(`${authConfig.serverUrl}/api/get-application?id=${owner}/${encodeURIComponent(name)}`, {
- method: "GET",
- credentials: "include"
- }).then(res => res.json());
-}
diff --git a/web/src/auth/AuthCallback.js b/web/src/auth/AuthCallback.js
index 6428716a..a5f6c525 100644
--- a/web/src/auth/AuthCallback.js
+++ b/web/src/auth/AuthCallback.js
@@ -34,7 +34,8 @@ class AuthCallback extends React.Component {
// realRedirectUrl = "http://localhost:9000"
const params = new URLSearchParams(this.props.location.search);
const state = params.get("state");
- return new URLSearchParams(Util.stateToGetQueryParams(state));
+ const queryString = Util.stateToGetQueryParams(state);
+ return new URLSearchParams(queryString);
}
getResponseType() {
@@ -42,14 +43,21 @@ class AuthCallback extends React.Component {
const authServerUrl = authConfig.serverUrl;
const innerParams = this.getInnerParams();
- const realRedirectUri = innerParams.get("redirect_uri");
- const realRedirectUrl = new URL(realRedirectUri).origin;
+ const method = innerParams.get("method");
+ if (method === "signup") {
+ const realRedirectUri = innerParams.get("redirect_uri");
+ const realRedirectUrl = new URL(realRedirectUri).origin;
- // For Casdoor itself, we use "login" directly
- if (authServerUrl === realRedirectUrl) {
- return "login";
+ // For Casdoor itself, we use "login" directly
+ if (authServerUrl === realRedirectUrl) {
+ return "login";
+ } else {
+ return "code";
+ }
+ } else if (method === "link") {
+ return "link";
} else {
- return "code";
+ return "unknown";
}
}
@@ -65,7 +73,8 @@ class AuthCallback extends React.Component {
application: applicationName,
provider: providerName,
code: params.get("code"),
- state: innerParams.get("state"),
+ // state: innerParams.get("state"),
+ state: innerParams.get("application"),
redirectUri: redirectUri,
method: method,
};
@@ -81,6 +90,9 @@ class AuthCallback extends React.Component {
const code = res.data;
Setting.goToLink(`${oAuthParams.redirectUri}?code=${code}&state=${oAuthParams.state}`);
// Util.showMessage("success", `Authorization code: ${res.data}`);
+ } else if (responseType === "link") {
+ const from = innerParams.get("from");
+ Setting.goToLinkSoft(this, from);
}
} else {
this.setState({
diff --git a/web/src/auth/LoginPage.js b/web/src/auth/LoginPage.js
index 09b97fa6..38ef5f79 100644
--- a/web/src/auth/LoginPage.js
+++ b/web/src/auth/LoginPage.js
@@ -17,6 +17,7 @@ import {Link} from "react-router-dom";
import {Button, Checkbox, Col, Form, Input, Row} from "antd";
import {LockOutlined, UserOutlined} from "@ant-design/icons";
import * as AuthBackend from "./AuthBackend";
+import * as ApplicationBackend from "../backend/ApplicationBackend";
import * as Provider from "./Provider";
import * as Util from "./Util";
import * as Setting from "../Setting";
@@ -68,7 +69,7 @@ class LoginPage extends React.Component {
return;
}
- AuthBackend.getApplication("admin", this.state.applicationName)
+ ApplicationBackend.getApplication("admin", this.state.applicationName)
.then((application) => {
this.setState({
application: application,
diff --git a/web/src/auth/Provider.js b/web/src/auth/Provider.js
index 86c45165..67b34abd 100644
--- a/web/src/auth/Provider.js
+++ b/web/src/auth/Provider.js
@@ -43,6 +43,10 @@ export function getAuthLogo(provider) {
}
export function getAuthUrl(application, provider, method) {
+ if (application === null || provider === null) {
+ return "";
+ }
+
const redirectUri = `${window.location.origin}/callback`;
const state = Util.getQueryParamsToState(application.name, provider.name, method);
if (provider.type === "Google") {
diff --git a/web/src/auth/Util.js b/web/src/auth/Util.js
index ab1dbf34..a4f8f724 100644
--- a/web/src/auth/Util.js
+++ b/web/src/auth/Util.js
@@ -111,6 +111,9 @@ export function getOAuthGetParameters(params) {
export function getQueryParamsToState(applicationName, providerName, method) {
let query = window.location.search;
query = `${query}&application=${applicationName}&provider=${providerName}&method=${method}`;
+ if (method === "link") {
+ query = `${query}&from=${window.location.pathname}`;
+ }
return btoa(query);
}
diff --git a/web/src/backend/ApplicationBackend.js b/web/src/backend/ApplicationBackend.js
index 68f5dc54..a85500f5 100644
--- a/web/src/backend/ApplicationBackend.js
+++ b/web/src/backend/ApplicationBackend.js
@@ -28,6 +28,13 @@ export function getApplication(owner, name) {
}).then(res => res.json());
}
+export function getDefaultApplication(owner) {
+ return fetch(`${Setting.ServerUrl}/api/get-default-application?owner=${owner}`, {
+ method: "GET",
+ credentials: "include"
+ }).then(res => res.json());
+}
+
export function updateApplication(owner, name, application) {
let newApplication = Setting.deepCopy(application);
return fetch(`${Setting.ServerUrl}/api/update-application?id=${owner}/${encodeURIComponent(name)}`, {
diff --git a/web/src/backend/ProviderBackend.js b/web/src/backend/ProviderBackend.js
index 9a055163..61177ea5 100644
--- a/web/src/backend/ProviderBackend.js
+++ b/web/src/backend/ProviderBackend.js
@@ -21,6 +21,13 @@ export function getProviders(owner) {
}).then(res => res.json());
}
+export function getDefaultProviders(owner) {
+ return fetch(`${Setting.ServerUrl}/api/get-default-providers?owner=${owner}`, {
+ method: "GET",
+ credentials: "include"
+ }).then(res => res.json());
+}
+
export function getProvider(owner, name) {
return fetch(`${Setting.ServerUrl}/api/get-provider?id=${owner}/${encodeURIComponent(name)}`, {
method: "GET",