mirror of
https://github.com/casdoor/casdoor.git
synced 2025-05-22 18:25:47 +08:00
feat: add UI to view logs
Signed-off-by: killer <1533063601@qq.com>
This commit is contained in:
parent
6ae8e537b9
commit
21b36bbb47
@ -181,6 +181,12 @@ func (c *ApiController) Login() {
|
||||
} else {
|
||||
application := object.GetApplication(fmt.Sprintf("admin/%s", form.Application))
|
||||
resp = c.HandleLoggedIn(application, user, &form)
|
||||
|
||||
record := util.Records(c.Ctx)
|
||||
record.Organization = application.Organization
|
||||
record.Username = user.Name
|
||||
|
||||
object.AddRecord(record)
|
||||
}
|
||||
} else if form.Provider != "" {
|
||||
application := object.GetApplication(fmt.Sprintf("admin/%s", form.Application))
|
||||
@ -252,6 +258,12 @@ func (c *ApiController) Login() {
|
||||
//}
|
||||
|
||||
resp = c.HandleLoggedIn(application, user, &form)
|
||||
|
||||
record := util.Records(c.Ctx)
|
||||
record.Organization = application.Organization
|
||||
record.Username = user.Name
|
||||
|
||||
object.AddRecord(record)
|
||||
} else {
|
||||
// Sign up via OAuth
|
||||
if !application.EnableSignUp {
|
||||
@ -294,6 +306,12 @@ func (c *ApiController) Login() {
|
||||
object.LinkUserAccount(user, provider.Type, userInfo.Id)
|
||||
|
||||
resp = c.HandleLoggedIn(application, user, &form)
|
||||
|
||||
record := util.Records(c.Ctx)
|
||||
record.Organization = application.Organization
|
||||
record.Username = user.Name
|
||||
|
||||
object.AddRecord(record)
|
||||
}
|
||||
//resp = &Response{Status: "ok", Msg: "", Data: res}
|
||||
} else { // form.Method != "signup"
|
||||
|
46
controllers/record.go
Normal file
46
controllers/record.go
Normal file
@ -0,0 +1,46 @@
|
||||
// Copyright 2021 The casbin Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/casdoor/casdoor/object"
|
||||
)
|
||||
|
||||
// @Title GetRecords
|
||||
// @Description get all records
|
||||
// @Success 200 {array} object.Records The Response object
|
||||
// @router /get-records [get]
|
||||
func (c *ApiController) GetRecords() {
|
||||
c.Data["json"] = object.GetRecords()
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// @Title GetRecordsByFilter
|
||||
// @Description get records by filter
|
||||
// @Param body body object.Records true "filter Record message"
|
||||
// @Success 200 {array} object.Records The Response object
|
||||
// @router /get-records-filter [post]
|
||||
func (c *ApiController) GetRecordsByFilter() {
|
||||
var record object.Records
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &record)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
c.Data["json"] = object.GetRecordsByField(&record)
|
||||
c.ServeJSON()
|
||||
}
|
1
main.go
1
main.go
@ -48,6 +48,7 @@ func main() {
|
||||
beego.InsertFilter("*", beego.BeforeRouter, routers.StaticFilter)
|
||||
beego.InsertFilter("*", beego.BeforeRouter, routers.AutoLoginFilter)
|
||||
beego.InsertFilter("*", beego.BeforeRouter, routers.AuthzFilter)
|
||||
beego.InsertFilter("*", beego.BeforeRouter, routers.RecordMessage)
|
||||
|
||||
beego.BConfig.WebConfig.Session.SessionName = "casdoor_session_id"
|
||||
beego.BConfig.WebConfig.Session.SessionProvider = "file"
|
||||
|
@ -133,4 +133,8 @@ func (a *Adapter) createTable() {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = a.Engine.Sync2(new(Records))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
65
object/record.go
Normal file
65
object/record.go
Normal file
@ -0,0 +1,65 @@
|
||||
// Copyright 2021 The casbin Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package object
|
||||
|
||||
import (
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
|
||||
type Records struct {
|
||||
Id int `xorm:"int notnull pk autoincr" json:"id"`
|
||||
Record util.Record `xorm:"extends"`
|
||||
}
|
||||
|
||||
func AddRecord(record *util.Record) bool {
|
||||
records := new(Records)
|
||||
records.Record = *record
|
||||
|
||||
affected, err := adapter.Engine.Insert(records)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return affected != 0
|
||||
}
|
||||
|
||||
func GetRecordCount() int {
|
||||
count, err := adapter.Engine.Count(&Records{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return int(count)
|
||||
}
|
||||
|
||||
func GetRecords() []*Records {
|
||||
records := []*Records{}
|
||||
err := adapter.Engine.Desc("id").Find(&records)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return records
|
||||
}
|
||||
|
||||
func GetRecordsByField(record *Records) []*Records {
|
||||
records := []*Records{}
|
||||
err := adapter.Engine.Find(&records, record)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return records
|
||||
}
|
70
routers/record.go
Normal file
70
routers/record.go
Normal file
@ -0,0 +1,70 @@
|
||||
// Copyright 2021 The casbin Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package routers
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/astaxie/beego/context"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
|
||||
func getUser(ctx *context.Context) (username string) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
username = getUserByClientIdSecret(ctx)
|
||||
}
|
||||
}()
|
||||
|
||||
username = ctx.Input.Session("username").(string)
|
||||
|
||||
if username == "" {
|
||||
username = getUserByClientIdSecret(ctx)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func getUserByClientIdSecret(ctx *context.Context) string {
|
||||
requestUri := ctx.Request.RequestURI
|
||||
clientId := parseQuery(requestUri, "clientId")
|
||||
clientSecret := parseQuery(requestUri, "clientSecret")
|
||||
if len(clientId) == 0 || len(clientSecret) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
app := object.GetApplicationByClientId(clientId)
|
||||
if app == nil || app.ClientSecret != clientSecret {
|
||||
return ""
|
||||
}
|
||||
return app.Organization+"/"+app.Name
|
||||
}
|
||||
|
||||
func RecordMessage(ctx *context.Context) {
|
||||
if ctx.Request.URL.Path != "/api/login" {
|
||||
user := getUser(ctx)
|
||||
userinfo := strings.Split(user,"/")
|
||||
if user == "" {
|
||||
userinfo = append(userinfo,"")
|
||||
}
|
||||
record := util.Records(ctx)
|
||||
record.Organization = userinfo[0]
|
||||
record.Username = userinfo[1]
|
||||
|
||||
object.AddRecord(record)
|
||||
}
|
||||
}
|
||||
|
@ -84,4 +84,8 @@ func initAPI() {
|
||||
beego.Router("/api/add-token", &controllers.ApiController{}, "POST:AddToken")
|
||||
beego.Router("/api/delete-token", &controllers.ApiController{}, "POST:DeleteToken")
|
||||
beego.Router("/api/login/oauth/access_token", &controllers.ApiController{}, "POST:GetOAuthToken")
|
||||
|
||||
beego.Router("/api/get-records", &controllers.ApiController{}, "GET:GetRecords")
|
||||
beego.Router("/api/get-records-filter", &controllers.ApiController{}, "POST:GetRecordsByFilter")
|
||||
}
|
||||
|
||||
|
@ -362,6 +362,65 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/get-default-application": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"api"
|
||||
],
|
||||
"description": "get the detail of the default application",
|
||||
"operationId": "ApiController.GetDefaultApplication",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "query",
|
||||
"name": "owner",
|
||||
"description": "The owner of the application.",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "The Response object",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/object.Application"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/get-email-and-phone": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"api"
|
||||
],
|
||||
"description": "get email and phone by username",
|
||||
"operationId": "ApiController.GetEmailAndPhone",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "formData",
|
||||
"name": "username",
|
||||
"description": "The username of the user",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"in": "formData",
|
||||
"name": "organization",
|
||||
"description": "The organization of the user",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "The Response object",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controllers.Response"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/get-global-users": {
|
||||
"get": {
|
||||
"tags": [
|
||||
@ -492,6 +551,57 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/get-records": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"api"
|
||||
],
|
||||
"description": "get all records",
|
||||
"operationId": "ApiController.GetRecords",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "The Response object",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/object.Records"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/get-records-filter": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"api"
|
||||
],
|
||||
"description": "get records by filter",
|
||||
"operationId": "ApiController.GetRecordsByFilter",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "body",
|
||||
"name": "body",
|
||||
"description": "filter Record message",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/object.Records"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "The Response object",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/object.Records"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/get-token": {
|
||||
"get": {
|
||||
"tags": [
|
||||
@ -700,18 +810,65 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/register": {
|
||||
"/api/set-password": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"api"
|
||||
],
|
||||
"description": "register a new user",
|
||||
"operationId": "ApiController.Register",
|
||||
"description": "set password",
|
||||
"operationId": "ApiController.SetPassword",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "formData",
|
||||
"name": "userOwner",
|
||||
"description": "The owner of the user",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"in": "formData",
|
||||
"name": "userName",
|
||||
"description": "The name of the user",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"in": "formData",
|
||||
"name": "oldPassword",
|
||||
"description": "The old password of the user",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"in": "formData",
|
||||
"name": "newPassword",
|
||||
"description": "The new password of the user",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "The Response object",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controllers.Response"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/signup": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"api"
|
||||
],
|
||||
"description": "sign up a new user",
|
||||
"operationId": "ApiController.Signup",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "formData",
|
||||
"name": "username",
|
||||
"description": "The username to register",
|
||||
"description": "The username to sign up",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
@ -965,7 +1122,7 @@
|
||||
"tags": [
|
||||
"api"
|
||||
],
|
||||
"description": "register a new user",
|
||||
"description": "upload avatar",
|
||||
"operationId": "ApiController.UploadAvatar",
|
||||
"parameters": [
|
||||
{
|
||||
@ -995,7 +1152,11 @@
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"1471.0xc0003bd890.false": {
|
||||
"1671.0xc00044ab10.false": {
|
||||
"title": "false",
|
||||
"type": "object"
|
||||
},
|
||||
"1705.0xc00044ab40.false": {
|
||||
"title": "false",
|
||||
"type": "object"
|
||||
},
|
||||
@ -1008,7 +1169,10 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/1471.0xc0003bd890.false"
|
||||
"$ref": "#/definitions/1671.0xc00044ab10.false"
|
||||
},
|
||||
"data2": {
|
||||
"$ref": "#/definitions/1705.0xc00044ab40.false"
|
||||
},
|
||||
"msg": {
|
||||
"type": "string"
|
||||
@ -1023,7 +1187,10 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/1471.0xc0003bd890.false"
|
||||
"$ref": "#/definitions/1671.0xc00044ab10.false"
|
||||
},
|
||||
"data2": {
|
||||
"$ref": "#/definitions/1705.0xc00044ab40.false"
|
||||
},
|
||||
"msg": {
|
||||
"type": "string"
|
||||
@ -1037,6 +1204,9 @@
|
||||
"title": "Application",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"affiliationUrl": {
|
||||
"type": "string"
|
||||
},
|
||||
"clientId": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -1062,6 +1232,9 @@
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"forgetUrl": {
|
||||
"type": "string"
|
||||
},
|
||||
"homepageUrl": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -1074,19 +1247,16 @@
|
||||
"organization": {
|
||||
"type": "string"
|
||||
},
|
||||
"organizationObj": {
|
||||
"$ref": "#/definitions/object.Organization"
|
||||
},
|
||||
"owner": {
|
||||
"type": "string"
|
||||
},
|
||||
"providerObjs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/object.Provider"
|
||||
}
|
||||
},
|
||||
"providers": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/object.ProviderItem"
|
||||
}
|
||||
},
|
||||
"redirectUris": {
|
||||
@ -1094,6 +1264,18 @@
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"signinUrl": {
|
||||
"type": "string"
|
||||
},
|
||||
"signupItems": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/object.SignupItem"
|
||||
}
|
||||
},
|
||||
"signupUrl": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -1104,15 +1286,30 @@
|
||||
"createdTime": {
|
||||
"type": "string"
|
||||
},
|
||||
"defaultAvatar": {
|
||||
"type": "string"
|
||||
},
|
||||
"displayName": {
|
||||
"type": "string"
|
||||
},
|
||||
"favicon": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"owner": {
|
||||
"type": "string"
|
||||
},
|
||||
"passwordSalt": {
|
||||
"type": "string"
|
||||
},
|
||||
"passwordType": {
|
||||
"type": "string"
|
||||
},
|
||||
"phonePrefix": {
|
||||
"type": "string"
|
||||
},
|
||||
"websiteUrl": {
|
||||
"type": "string"
|
||||
}
|
||||
@ -1122,32 +1319,121 @@
|
||||
"title": "Provider",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"appId": {
|
||||
"type": "string"
|
||||
},
|
||||
"category": {
|
||||
"type": "string"
|
||||
},
|
||||
"clientId": {
|
||||
"type": "string"
|
||||
},
|
||||
"clientSecret": {
|
||||
"type": "string"
|
||||
},
|
||||
"content": {
|
||||
"type": "string"
|
||||
},
|
||||
"createdTime": {
|
||||
"type": "string"
|
||||
},
|
||||
"displayName": {
|
||||
"type": "string"
|
||||
},
|
||||
"host": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"owner": {
|
||||
"type": "string"
|
||||
},
|
||||
"port": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"providerUrl": {
|
||||
"type": "string"
|
||||
},
|
||||
"regionId": {
|
||||
"type": "string"
|
||||
},
|
||||
"signName": {
|
||||
"type": "string"
|
||||
},
|
||||
"templateCode": {
|
||||
"type": "string"
|
||||
},
|
||||
"title": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"object.ProviderItem": {
|
||||
"title": "ProviderItem",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"alertType": {
|
||||
"type": "string"
|
||||
},
|
||||
"canSignIn": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"canSignUp": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"canUnlink": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"prompted": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"provider": {
|
||||
"$ref": "#/definitions/object.Provider"
|
||||
}
|
||||
}
|
||||
},
|
||||
"object.Records": {
|
||||
"title": "Records",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Record": {
|
||||
"$ref": "#/definitions/util.Record"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
}
|
||||
},
|
||||
"object.SignupItem": {
|
||||
"title": "SignupItem",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"prompted": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"required": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"rule": {
|
||||
"type": "string"
|
||||
},
|
||||
"visible": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"object.Token": {
|
||||
"title": "Token",
|
||||
"type": "object",
|
||||
@ -1171,6 +1457,9 @@
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"organization": {
|
||||
"type": "string"
|
||||
},
|
||||
"owner": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -1179,6 +1468,9 @@
|
||||
},
|
||||
"tokenType": {
|
||||
"type": "string"
|
||||
},
|
||||
"user": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -1205,6 +1497,12 @@
|
||||
"title": "User",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"address": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"affiliation": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -1214,27 +1512,45 @@
|
||||
"createdTime": {
|
||||
"type": "string"
|
||||
},
|
||||
"dingtalk": {
|
||||
"type": "string"
|
||||
},
|
||||
"displayName": {
|
||||
"type": "string"
|
||||
},
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"facebook": {
|
||||
"type": "string"
|
||||
},
|
||||
"gitee": {
|
||||
"type": "string"
|
||||
},
|
||||
"github": {
|
||||
"type": "string"
|
||||
},
|
||||
"google": {
|
||||
"type": "string"
|
||||
},
|
||||
"hash": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"isAdmin": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"isForbidden": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"isGlobalAdmin": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"language": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -1244,17 +1560,65 @@
|
||||
"password": {
|
||||
"type": "string"
|
||||
},
|
||||
"passwordType": {
|
||||
"type": "string"
|
||||
},
|
||||
"phone": {
|
||||
"type": "string"
|
||||
},
|
||||
"preHash": {
|
||||
"type": "string"
|
||||
},
|
||||
"properties": {
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"qq": {
|
||||
"type": "string"
|
||||
},
|
||||
"score": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"signupApplication": {
|
||||
"type": "string"
|
||||
},
|
||||
"tag": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
},
|
||||
"updatedTime": {
|
||||
"type": "string"
|
||||
},
|
||||
"wechat": {
|
||||
"type": "string"
|
||||
},
|
||||
"weibo": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"util.Record": {
|
||||
"title": "Record",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"ip": {
|
||||
"type": "string"
|
||||
},
|
||||
"organization": {
|
||||
"type": "string"
|
||||
},
|
||||
"requestTime": {
|
||||
"type": "string"
|
||||
},
|
||||
"requestUri": {
|
||||
"type": "string"
|
||||
},
|
||||
"urlpath": {
|
||||
"type": "string"
|
||||
},
|
||||
"username": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -234,6 +234,45 @@ paths:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/object.Application'
|
||||
/api/get-default-application:
|
||||
get:
|
||||
tags:
|
||||
- api
|
||||
description: get the detail of the default application
|
||||
operationId: ApiController.GetDefaultApplication
|
||||
parameters:
|
||||
- in: query
|
||||
name: owner
|
||||
description: The owner of the application.
|
||||
required: true
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/object.Application'
|
||||
/api/get-email-and-phone:
|
||||
post:
|
||||
tags:
|
||||
- api
|
||||
description: get email and phone by username
|
||||
operationId: ApiController.GetEmailAndPhone
|
||||
parameters:
|
||||
- in: formData
|
||||
name: username
|
||||
description: The username of the user
|
||||
required: true
|
||||
type: string
|
||||
- in: formData
|
||||
name: organization
|
||||
description: The organization of the user
|
||||
required: true
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.Response'
|
||||
/api/get-global-users:
|
||||
get:
|
||||
tags:
|
||||
@ -319,6 +358,39 @@ paths:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/object.Provider'
|
||||
/api/get-records:
|
||||
get:
|
||||
tags:
|
||||
- api
|
||||
description: get all records
|
||||
operationId: ApiController.GetRecords
|
||||
responses:
|
||||
"200":
|
||||
description: The Response object
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/object.Records'
|
||||
/api/get-records-filter:
|
||||
post:
|
||||
tags:
|
||||
- api
|
||||
description: get records by filter
|
||||
operationId: ApiController.GetRecordsByFilter
|
||||
parameters:
|
||||
- in: body
|
||||
name: body
|
||||
description: filter Record message
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/object.Records'
|
||||
responses:
|
||||
"200":
|
||||
description: The Response object
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/object.Records'
|
||||
/api/get-token:
|
||||
get:
|
||||
tags:
|
||||
@ -456,16 +528,48 @@ paths:
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.Response'
|
||||
/api/register:
|
||||
/api/set-password:
|
||||
post:
|
||||
tags:
|
||||
- api
|
||||
description: register a new user
|
||||
operationId: ApiController.Register
|
||||
description: set password
|
||||
operationId: ApiController.SetPassword
|
||||
parameters:
|
||||
- in: formData
|
||||
name: userOwner
|
||||
description: The owner of the user
|
||||
required: true
|
||||
type: string
|
||||
- in: formData
|
||||
name: userName
|
||||
description: The name of the user
|
||||
required: true
|
||||
type: string
|
||||
- in: formData
|
||||
name: oldPassword
|
||||
description: The old password of the user
|
||||
required: true
|
||||
type: string
|
||||
- in: formData
|
||||
name: newPassword
|
||||
description: The new password of the user
|
||||
required: true
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.Response'
|
||||
/api/signup:
|
||||
post:
|
||||
tags:
|
||||
- api
|
||||
description: sign up a new user
|
||||
operationId: ApiController.Signup
|
||||
parameters:
|
||||
- in: formData
|
||||
name: username
|
||||
description: The username to register
|
||||
description: The username to sign up
|
||||
required: true
|
||||
type: string
|
||||
- in: formData
|
||||
@ -633,7 +737,7 @@ paths:
|
||||
post:
|
||||
tags:
|
||||
- api
|
||||
description: register a new user
|
||||
description: upload avatar
|
||||
operationId: ApiController.UploadAvatar
|
||||
parameters:
|
||||
- in: formData
|
||||
@ -652,7 +756,10 @@ paths:
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.Response'
|
||||
definitions:
|
||||
1471.0xc0003bd890.false:
|
||||
1671.0xc00044ab10.false:
|
||||
title: "false"
|
||||
type: object
|
||||
1705.0xc00044ab40.false:
|
||||
title: "false"
|
||||
type: object
|
||||
RequestForm:
|
||||
@ -663,7 +770,9 @@ definitions:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/definitions/1471.0xc0003bd890.false'
|
||||
$ref: '#/definitions/1671.0xc00044ab10.false'
|
||||
data2:
|
||||
$ref: '#/definitions/1705.0xc00044ab40.false'
|
||||
msg:
|
||||
type: string
|
||||
status:
|
||||
@ -673,7 +782,9 @@ definitions:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/definitions/1471.0xc0003bd890.false'
|
||||
$ref: '#/definitions/1671.0xc00044ab10.false'
|
||||
data2:
|
||||
$ref: '#/definitions/1705.0xc00044ab40.false'
|
||||
msg:
|
||||
type: string
|
||||
status:
|
||||
@ -682,6 +793,8 @@ definitions:
|
||||
title: Application
|
||||
type: object
|
||||
properties:
|
||||
affiliationUrl:
|
||||
type: string
|
||||
clientId:
|
||||
type: string
|
||||
clientSecret:
|
||||
@ -699,6 +812,8 @@ definitions:
|
||||
expireInHours:
|
||||
type: integer
|
||||
format: int64
|
||||
forgetUrl:
|
||||
type: string
|
||||
homepageUrl:
|
||||
type: string
|
||||
logo:
|
||||
@ -707,54 +822,130 @@ definitions:
|
||||
type: string
|
||||
organization:
|
||||
type: string
|
||||
organizationObj:
|
||||
$ref: '#/definitions/object.Organization'
|
||||
owner:
|
||||
type: string
|
||||
providerObjs:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/object.Provider'
|
||||
providers:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
$ref: '#/definitions/object.ProviderItem'
|
||||
redirectUris:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
signinUrl:
|
||||
type: string
|
||||
signupItems:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/object.SignupItem'
|
||||
signupUrl:
|
||||
type: string
|
||||
object.Organization:
|
||||
title: Organization
|
||||
type: object
|
||||
properties:
|
||||
createdTime:
|
||||
type: string
|
||||
defaultAvatar:
|
||||
type: string
|
||||
displayName:
|
||||
type: string
|
||||
favicon:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
owner:
|
||||
type: string
|
||||
passwordSalt:
|
||||
type: string
|
||||
passwordType:
|
||||
type: string
|
||||
phonePrefix:
|
||||
type: string
|
||||
websiteUrl:
|
||||
type: string
|
||||
object.Provider:
|
||||
title: Provider
|
||||
type: object
|
||||
properties:
|
||||
appId:
|
||||
type: string
|
||||
category:
|
||||
type: string
|
||||
clientId:
|
||||
type: string
|
||||
clientSecret:
|
||||
type: string
|
||||
content:
|
||||
type: string
|
||||
createdTime:
|
||||
type: string
|
||||
displayName:
|
||||
type: string
|
||||
host:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
owner:
|
||||
type: string
|
||||
port:
|
||||
type: integer
|
||||
format: int64
|
||||
providerUrl:
|
||||
type: string
|
||||
regionId:
|
||||
type: string
|
||||
signName:
|
||||
type: string
|
||||
templateCode:
|
||||
type: string
|
||||
title:
|
||||
type: string
|
||||
type:
|
||||
type: string
|
||||
object.ProviderItem:
|
||||
title: ProviderItem
|
||||
type: object
|
||||
properties:
|
||||
alertType:
|
||||
type: string
|
||||
canSignIn:
|
||||
type: boolean
|
||||
canSignUp:
|
||||
type: boolean
|
||||
canUnlink:
|
||||
type: boolean
|
||||
name:
|
||||
type: string
|
||||
prompted:
|
||||
type: boolean
|
||||
provider:
|
||||
$ref: '#/definitions/object.Provider'
|
||||
object.Records:
|
||||
title: Records
|
||||
type: object
|
||||
properties:
|
||||
Record:
|
||||
$ref: '#/definitions/util.Record'
|
||||
id:
|
||||
type: integer
|
||||
format: int64
|
||||
object.SignupItem:
|
||||
title: SignupItem
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
prompted:
|
||||
type: boolean
|
||||
required:
|
||||
type: boolean
|
||||
rule:
|
||||
type: string
|
||||
visible:
|
||||
type: boolean
|
||||
object.Token:
|
||||
title: Token
|
||||
type: object
|
||||
@ -772,12 +963,16 @@ definitions:
|
||||
format: int64
|
||||
name:
|
||||
type: string
|
||||
organization:
|
||||
type: string
|
||||
owner:
|
||||
type: string
|
||||
scope:
|
||||
type: string
|
||||
tokenType:
|
||||
type: string
|
||||
user:
|
||||
type: string
|
||||
object.TokenWrapper:
|
||||
title: TokenWrapper
|
||||
type: object
|
||||
@ -795,37 +990,85 @@ definitions:
|
||||
title: User
|
||||
type: object
|
||||
properties:
|
||||
address:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
affiliation:
|
||||
type: string
|
||||
avatar:
|
||||
type: string
|
||||
createdTime:
|
||||
type: string
|
||||
dingtalk:
|
||||
type: string
|
||||
displayName:
|
||||
type: string
|
||||
email:
|
||||
type: string
|
||||
facebook:
|
||||
type: string
|
||||
gitee:
|
||||
type: string
|
||||
github:
|
||||
type: string
|
||||
google:
|
||||
type: string
|
||||
hash:
|
||||
type: string
|
||||
id:
|
||||
type: string
|
||||
isAdmin:
|
||||
type: boolean
|
||||
isForbidden:
|
||||
type: boolean
|
||||
isGlobalAdmin:
|
||||
type: boolean
|
||||
language:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
owner:
|
||||
type: string
|
||||
password:
|
||||
type: string
|
||||
passwordType:
|
||||
type: string
|
||||
phone:
|
||||
type: string
|
||||
preHash:
|
||||
type: string
|
||||
properties:
|
||||
additionalProperties:
|
||||
type: string
|
||||
qq:
|
||||
type: string
|
||||
score:
|
||||
type: integer
|
||||
format: int64
|
||||
signupApplication:
|
||||
type: string
|
||||
tag:
|
||||
type: string
|
||||
type:
|
||||
type: string
|
||||
updatedTime:
|
||||
type: string
|
||||
wechat:
|
||||
type: string
|
||||
weibo:
|
||||
type: string
|
||||
util.Record:
|
||||
title: Record
|
||||
type: object
|
||||
properties:
|
||||
ip:
|
||||
type: string
|
||||
organization:
|
||||
type: string
|
||||
requestTime:
|
||||
type: string
|
||||
requestUri:
|
||||
type: string
|
||||
urlpath:
|
||||
type: string
|
||||
username:
|
||||
type: string
|
||||
|
47
util/record.go
Normal file
47
util/record.go
Normal file
@ -0,0 +1,47 @@
|
||||
// Copyright 2021 The casbin Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package util
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/astaxie/beego/context"
|
||||
)
|
||||
|
||||
type Record struct {
|
||||
ClientIp string `xorm:"varchar(100)" json:"clientIp"`
|
||||
Timestamp string `xorm:"varchar(100)" json:"timestamp"`
|
||||
Organization string `xorm:"varchar(100)" json:"organization"`
|
||||
Username string `xorm:"varchar(100)" json:"username"`
|
||||
RequestUri string `xorm:"varchar(1000)" json:"requestUri"`
|
||||
Action string `xorm:"varchar(1000)" json:"action"`
|
||||
}
|
||||
|
||||
func Records(ctx *context.Context) *Record {
|
||||
ip := strings.Replace(getIPFromRequest(ctx.Request), ": ", "", -1)
|
||||
currenttime := GetCurrentTime()
|
||||
requesturi := ctx.Request.RequestURI
|
||||
action := strings.Replace(ctx.Request.URL.Path, "/api/", "", -1)
|
||||
|
||||
record := Record{
|
||||
ClientIp: ip,
|
||||
Timestamp: currenttime,
|
||||
RequestUri: requesturi,
|
||||
Username: "",
|
||||
Organization: "",
|
||||
Action: action,
|
||||
}
|
||||
return &record
|
||||
}
|
@ -29,6 +29,7 @@ import ApplicationListPage from "./ApplicationListPage";
|
||||
import ApplicationEditPage from "./ApplicationEditPage";
|
||||
import TokenListPage from "./TokenListPage";
|
||||
import TokenEditPage from "./TokenEditPage";
|
||||
import RecordListPage from "./RecordListPage";
|
||||
import AccountPage from "./account/AccountPage";
|
||||
import HomePage from "./basic/HomePage";
|
||||
import CustomGithubCorner from "./CustomGithubCorner";
|
||||
@ -317,6 +318,13 @@ class App extends Component {
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
);
|
||||
res.push(
|
||||
<Menu.Item key="7">
|
||||
<Link to="/records">
|
||||
{i18next.t("general:Records")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
);
|
||||
}
|
||||
res.push(
|
||||
<Menu.Item key="6" onClick={() => window.location.href = "/swagger"}>
|
||||
@ -392,6 +400,7 @@ class App extends Component {
|
||||
<Route exact path="/applications/:applicationName" render={(props) => this.renderLoginIfNotLoggedIn(<ApplicationEditPage account={this.state.account} {...props} />)}/>
|
||||
<Route exact path="/tokens" render={(props) => this.renderLoginIfNotLoggedIn(<TokenListPage account={this.state.account} {...props} />)}/>
|
||||
<Route exact path="/tokens/:tokenName" render={(props) => this.renderLoginIfNotLoggedIn(<TokenEditPage account={this.state.account} {...props} />)}/>
|
||||
<Route exact path="/records" render={(props) => this.renderLoginIfNotLoggedIn(<RecordListPage account={this.state.account} {...props} />)}/>
|
||||
</Switch>
|
||||
</div>
|
||||
)
|
||||
|
159
web/src/RecordListPage.js
Normal file
159
web/src/RecordListPage.js
Normal file
@ -0,0 +1,159 @@
|
||||
// Copyright 2021 The casbin Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import React from "react";
|
||||
import {Link} from "react-router-dom";
|
||||
import {Col, Row, Table} from 'antd';
|
||||
import * as Setting from "./Setting";
|
||||
import * as RecordBackend from "./backend/RecordBackend";
|
||||
import i18next from "i18next";
|
||||
|
||||
class RecordListPage extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
classes: props,
|
||||
records: null,
|
||||
};
|
||||
}
|
||||
|
||||
UNSAFE_componentWillMount() {
|
||||
this.getRecords();
|
||||
}
|
||||
|
||||
getRecords() {
|
||||
RecordBackend.getRecords()
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
records: res,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
newRecord() {
|
||||
return {
|
||||
id : "",
|
||||
Record:{
|
||||
clientIp:"",
|
||||
timestamp:"",
|
||||
organization:"",
|
||||
username:"",
|
||||
requestUri:"",
|
||||
action:"login",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
renderTable(records) {
|
||||
const columns = [
|
||||
{
|
||||
title: i18next.t("general:Client ip"),
|
||||
dataIndex: 'Record',
|
||||
key: 'Record',
|
||||
width: '120px',
|
||||
sorter: (a, b) => a.Record.clientIp.localeCompare(b.Record.clientIp),
|
||||
render: (text, record, index) => {
|
||||
return text.clientIp;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Timestamp"),
|
||||
dataIndex: 'Record',
|
||||
key: 'Record',
|
||||
width: '160px',
|
||||
sorter: (a, b) => a.Record.timestamp.localeCompare(b.Record.timestamp),
|
||||
render: (text, record, index) => {
|
||||
return Setting.getFormattedDate(text.timestamp);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Organization"),
|
||||
dataIndex: 'Record',
|
||||
key: 'Record',
|
||||
width: '120px',
|
||||
sorter: (a, b) => a.Record.organization.localeCompare(b.Record.organization),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Link to={`/organizations/${text.organization}`}>
|
||||
{text.organization}
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Username"),
|
||||
dataIndex: 'Record',
|
||||
key: 'Record',
|
||||
width: '160px',
|
||||
sorter: (a, b) => a.Record.username.localeCompare(b.Record.username),
|
||||
render: (text, record, index) => {
|
||||
return text.username;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Request uri"),
|
||||
dataIndex: 'Record',
|
||||
key: 'Record',
|
||||
width: '160px',
|
||||
sorter: (a, b) => a.Record.requestUri.localeCompare(b.Record.requestUri),
|
||||
render: (text, record, index) => {
|
||||
return text.requestUri;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Action"),
|
||||
dataIndex: 'Record',
|
||||
key: 'Record',
|
||||
width: '160px',
|
||||
sorter: (a, b) => a.Record.action.localeCompare(b.Record.action),
|
||||
render: (text, record, index) => {
|
||||
return text.action;
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Table columns={columns} dataSource={records} rowKey="name" size="middle" bordered pagination={{pageSize: 100}}
|
||||
title={() => (
|
||||
<div>
|
||||
{i18next.t("general:Records")}
|
||||
</div>
|
||||
)}
|
||||
loading={records === null}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Row style={{width: "100%"}}>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
<Col span={22}>
|
||||
{
|
||||
this.renderTable(this.state.records)
|
||||
}
|
||||
</Col>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default RecordListPage;
|
22
web/src/backend/RecordBackend.js
Normal file
22
web/src/backend/RecordBackend.js
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2021 The casbin Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import * as Setting from "../Setting";
|
||||
|
||||
export function getRecords() {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-records`, {
|
||||
method: "GET",
|
||||
credentials: "include"
|
||||
}).then(res => res.json());
|
||||
}
|
@ -13,6 +13,11 @@
|
||||
"User": "User",
|
||||
"Applications": "Applications",
|
||||
"Application": "Application",
|
||||
"Records": "Records",
|
||||
"Client ip": "Client ip",
|
||||
"Timestamp": "Timestamp",
|
||||
"Username": "Username",
|
||||
"Request uri": "Request uri",
|
||||
"Save": "Save",
|
||||
"Add": "Add",
|
||||
"Action": "Action",
|
||||
|
Loading…
x
Reference in New Issue
Block a user