POC restricted access
This commit is contained in:
parent
76070ac882
commit
1958eb16fc
129
src/api/api.go
129
src/api/api.go
@ -16,6 +16,14 @@ const (
|
|||||||
profiler_API_PROCESS_REQUEST string = "API Process Request"
|
profiler_API_PROCESS_REQUEST string = "API Process Request"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type apiUserDefinition struct {
|
||||||
|
Id string
|
||||||
|
Name string
|
||||||
|
Permission string
|
||||||
|
}
|
||||||
|
|
||||||
|
type apiHandleAdminFunction func(http.ResponseWriter, *http.Request, httprouter.Params, apiUserDefinition)
|
||||||
|
|
||||||
var apiRootPath string = "/api/v1"
|
var apiRootPath string = "/api/v1"
|
||||||
|
|
||||||
func Init(router *httprouter.Router) {
|
func Init(router *httprouter.Router) {
|
||||||
@ -34,7 +42,7 @@ func Init(router *httprouter.Router) {
|
|||||||
router.GET(apiRootPath+"/page/:folder/:page/content", apiHandler(apiPageFolderPageContent))
|
router.GET(apiRootPath+"/page/:folder/:page/content", apiHandler(apiPageFolderPageContent))
|
||||||
|
|
||||||
router.GET(apiRootPath+"/user", apiHandler(apiUser))
|
router.GET(apiRootPath+"/user", apiHandler(apiUser))
|
||||||
router.POST(apiRootPath+"/user/:name", apiHandler(apiUser_Create))
|
router.POST(apiRootPath+"/user/:name", apiHandler(apiAdminRestricted(apiUser_Create)))
|
||||||
router.GET(apiRootPath+"/user/:name", apiHandler(apiUserName))
|
router.GET(apiRootPath+"/user/:name", apiHandler(apiUserName))
|
||||||
|
|
||||||
router.GET(apiRootPath+"/tag", apiHandler(apiTag))
|
router.GET(apiRootPath+"/tag", apiHandler(apiTag))
|
||||||
@ -58,6 +66,80 @@ func apiHandler(h httprouter.Handle) httprouter.Handle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func apiAdminRestricted(h apiHandleAdminFunction) httprouter.Handle {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||||
|
var auth string = r.Header.Get("Authorization")
|
||||||
|
if auth == "" {
|
||||||
|
writeErrorJSON(w, "", http.StatusForbidden)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const lenBearer int = len("Bearer ")
|
||||||
|
if auth[:lenBearer] != "Bearer " {
|
||||||
|
writeErrorJSON(w, "", http.StatusForbidden)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var token string = auth[lenBearer:]
|
||||||
|
|
||||||
|
var result database.DatabaseResult = database.ExecuteStoredRoutine("CheckAuthToken", token)
|
||||||
|
database.DecodeDatabaseResult(&result)
|
||||||
|
if result.ParsedResultLength == 0 {
|
||||||
|
writeErrorJSON(w, "", http.StatusForbidden)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var user apiUserDefinition = apiUserDefinition{
|
||||||
|
Id: result.ParsedResult["userId"][0].String,
|
||||||
|
Name: result.ParsedResult["userName"][0].String,
|
||||||
|
Permission: result.ParsedResult["userPermission"][0].String,
|
||||||
|
}
|
||||||
|
|
||||||
|
if user.Permission != "ADMIN" {
|
||||||
|
writeErrorJSON(w, "", http.StatusForbidden)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
h(w, r, ps, user)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func apiModeratorRestricted(h apiHandleAdminFunction) httprouter.Handle {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||||
|
var auth string = r.Header.Get("Authorization")
|
||||||
|
if auth == "" {
|
||||||
|
writeErrorJSON(w, "", http.StatusForbidden)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const lenBearer int = len("Bearer ")
|
||||||
|
if auth[:lenBearer] != "Bearer " {
|
||||||
|
writeErrorJSON(w, "", http.StatusForbidden)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var token string = auth[lenBearer:]
|
||||||
|
|
||||||
|
var result database.DatabaseResult = database.ExecuteStoredRoutine("CheckAuthToken", token)
|
||||||
|
database.DecodeDatabaseResult(&result)
|
||||||
|
if result.ParsedResultLength == 0 {
|
||||||
|
writeErrorJSON(w, "", http.StatusForbidden)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var user apiUserDefinition = apiUserDefinition{
|
||||||
|
Id: result.ParsedResult["userId"][0].String,
|
||||||
|
Name: result.ParsedResult["userName"][0].String,
|
||||||
|
Permission: result.ParsedResult["userPermission"][0].String,
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user.Permission != "ADMIN") && (user.Permission != "MODERATOR") {
|
||||||
|
writeErrorJSON(w, "", http.StatusForbidden)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
h(w, r, ps, user)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// API ROOT
|
// API ROOT
|
||||||
|
|
||||||
func apiRoot(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
func apiRoot(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||||
@ -68,11 +150,20 @@ func apiRoot(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
|||||||
// API Auth
|
// API Auth
|
||||||
|
|
||||||
func apiAuth(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
func apiAuth(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||||
fmt.Fprintf(w, "API Auth")
|
var ok bool
|
||||||
|
var id, name, permission string
|
||||||
|
ok, id, name, permission = verifyToken(r)
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
writeErrorJSON(w, "Authentification required", http.StatusForbidden)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(w, "{\"User\": {\"Id\": %s, \"Name\": \"%s\", \"Permission\": \"%s\"}}", id, name, permission)
|
||||||
}
|
}
|
||||||
|
|
||||||
func apiAuthLogin(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
func apiAuthLogin(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||||
fmt.Fprintf(w, "API Auth Login")
|
fmt.Fprintf(w, "API Auth Login\n")
|
||||||
r.ParseForm()
|
r.ParseForm()
|
||||||
var username string = r.FormValue("username")
|
var username string = r.FormValue("username")
|
||||||
var password string = r.FormValue("password")
|
var password string = r.FormValue("password")
|
||||||
@ -118,7 +209,7 @@ func apiUser(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
|||||||
fmt.Println(result)
|
fmt.Println(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
func apiUser_Create(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
|
func apiUser_Create(w http.ResponseWriter, r *http.Request, params httprouter.Params, _ apiUserDefinition) {
|
||||||
r.ParseForm()
|
r.ParseForm()
|
||||||
var username string = params.ByName("name")
|
var username string = params.ByName("name")
|
||||||
var password string = r.FormValue("password")
|
var password string = r.FormValue("password")
|
||||||
@ -174,6 +265,9 @@ func apiDebugDatabaseReset(w http.ResponseWriter, r *http.Request, _ httprouter.
|
|||||||
fmt.Fprintf(w, "Init Database...\n")
|
fmt.Fprintf(w, "Init Database...\n")
|
||||||
w.(http.Flusher).Flush()
|
w.(http.Flusher).Flush()
|
||||||
database.UpdateDatabaseStructure()
|
database.UpdateDatabaseStructure()
|
||||||
|
fmt.Fprintf(w, "Setup default conf...\n")
|
||||||
|
database.ExecuteStoredRoutine("CreateUser", "admin", "admin")
|
||||||
|
database.ExecuteStoredRoutine("UpdateUser", "1", nil, "ADMIN", "NULL")
|
||||||
fmt.Fprintf(w, "Done")
|
fmt.Fprintf(w, "Done")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,3 +299,30 @@ func setHeaderStream(w http.ResponseWriter) {
|
|||||||
w.Header().Set("Cache-Control", "no-cache")
|
w.Header().Set("Cache-Control", "no-cache")
|
||||||
w.Header().Set("Connection", "keep-alive")
|
w.Header().Set("Connection", "keep-alive")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func verifyToken(r *http.Request) (bool, string, string, string) {
|
||||||
|
var auth string = r.Header.Get("Authorization")
|
||||||
|
if auth == "" {
|
||||||
|
return false, "", "", ""
|
||||||
|
}
|
||||||
|
|
||||||
|
const lenBearer int = len("Bearer ")
|
||||||
|
if auth[:lenBearer] != "Bearer " {
|
||||||
|
return false, "", "", ""
|
||||||
|
}
|
||||||
|
var token string = auth[lenBearer:]
|
||||||
|
|
||||||
|
var result database.DatabaseResult = database.ExecuteStoredRoutine("CheckAuthToken", token)
|
||||||
|
database.DecodeDatabaseResult(&result)
|
||||||
|
if result.ParsedResultLength == 0 {
|
||||||
|
return false, "", "", ""
|
||||||
|
}
|
||||||
|
|
||||||
|
var id, name, permission string = result.ParsedResult["userId"][0].String, result.ParsedResult["userName"][0].String, result.ParsedResult["userPermission"][0].String
|
||||||
|
|
||||||
|
return true, id, name, permission
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeErrorJSON(w http.ResponseWriter, message string, codeRet int) {
|
||||||
|
http.Error(w, fmt.Sprintf("{\"Error\": {\"Code\": %d, \"Message\": \"%s\"}}", codeRet, message), codeRet)
|
||||||
|
}
|
||||||
|
@ -32,10 +32,11 @@ func (e *DatabaseError) HasError() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type DatabaseResult struct {
|
type DatabaseResult struct {
|
||||||
Error DatabaseError
|
Error DatabaseError
|
||||||
SqlRows *sql.Rows
|
SqlRows *sql.Rows
|
||||||
SqlResult sql.Result
|
SqlResult sql.Result
|
||||||
ParsedResult map[string][]sql.NullString
|
ParsedResultLength int64
|
||||||
|
ParsedResult map[string][]sql.NullString
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -256,6 +257,16 @@ var databaseStructure databaseDefinition = databaseDefinition{
|
|||||||
Name: "user_id",
|
Name: "user_id",
|
||||||
Type: "int(11)",
|
Type: "int(11)",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "creation",
|
||||||
|
Type: "DATE",
|
||||||
|
Default: "CURRENT_TIMESTAMP()",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "valid_until",
|
||||||
|
Type: "DATE",
|
||||||
|
Default: "NOW()",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -281,51 +292,6 @@ var databaseStructure databaseDefinition = databaseDefinition{
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Indexes: []indexDefinition{
|
Indexes: []indexDefinition{
|
||||||
// PRIMARY KEYS
|
|
||||||
/*
|
|
||||||
{
|
|
||||||
Name: "",
|
|
||||||
Type: database_ENUM_INDEX_PRIMARY,
|
|
||||||
Table: "user",
|
|
||||||
Columns: []string{
|
|
||||||
"id",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "",
|
|
||||||
Type: database_ENUM_INDEX_PRIMARY,
|
|
||||||
Table: "folder",
|
|
||||||
Columns: []string{
|
|
||||||
"id",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "",
|
|
||||||
Type: database_ENUM_INDEX_PRIMARY,
|
|
||||||
Table: "tag",
|
|
||||||
Columns: []string{
|
|
||||||
"id",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "",
|
|
||||||
Type: database_ENUM_INDEX_PRIMARY,
|
|
||||||
Table: "website",
|
|
||||||
Columns: []string{
|
|
||||||
"id",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "",
|
|
||||||
Type: database_ENUM_INDEX_PRIMARY,
|
|
||||||
Table: "tags_websites",
|
|
||||||
Columns: []string{
|
|
||||||
"tag_id",
|
|
||||||
"website_id",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
*/
|
|
||||||
|
|
||||||
// UNIQUE KEYS
|
// UNIQUE KEYS
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -380,6 +346,58 @@ var databaseStructure databaseDefinition = databaseDefinition{
|
|||||||
Name: "ListUsers",
|
Name: "ListUsers",
|
||||||
Command: "SELECT id, name, permission_level FROM user;",
|
Command: "SELECT id, name, permission_level FROM user;",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "GetUserCount",
|
||||||
|
Command: "SELECT COUNT(user.id) as userCount FROM user;",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "GetWebsiteCount",
|
||||||
|
Command: "SELECT COUNT(website.id) as websiteCount FROM website;",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "CheckAuthToken",
|
||||||
|
Parameters: []storedRoutineParameterDefinition{
|
||||||
|
{
|
||||||
|
Name: "f_token",
|
||||||
|
Type: "VARCHAR(256)",
|
||||||
|
Charset: "utf8mb4",
|
||||||
|
Collation: "utf8mb4_bin",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Command: "SELECT user.id as userId, user.name as userName, user.permission_level as userPermission FROM loginToken INNER JOIN user ON user.id = loginToken.user_id WHERE f_token = loginToken.id LIMIT 1;",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "UpdateUser",
|
||||||
|
Parameters: []storedRoutineParameterDefinition{
|
||||||
|
{
|
||||||
|
Name: "f_user_id",
|
||||||
|
Type: "int(11)",
|
||||||
|
IsNullable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "f_new_name",
|
||||||
|
Type: "VARCHAR(256)",
|
||||||
|
Charset: "utf8mb4",
|
||||||
|
Collation: "utf8mb4_unicode_ci",
|
||||||
|
IsNullable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "f_new_permission_level",
|
||||||
|
Type: "VARCHAR(32)",
|
||||||
|
Charset: "utf8mb4",
|
||||||
|
Collation: "utf8mb4_unicode_ci",
|
||||||
|
IsNullable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "f_new_email",
|
||||||
|
Type: "VARCHAR(256)",
|
||||||
|
Charset: "utf8mb4",
|
||||||
|
Collation: "utf8mb4_unicode_ci",
|
||||||
|
IsNullable: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Command: "UPDATE user SET name = IFNULL(f_new_name, name), permission_level = IFNULL(f_new_permission_level, permission_level), email = IFNULL(f_new_email, email);",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
StoredFunctions: []storedFunctionDefinition{
|
StoredFunctions: []storedFunctionDefinition{
|
||||||
{
|
{
|
||||||
@ -484,7 +502,7 @@ func connect() {
|
|||||||
var err error
|
var err error
|
||||||
log.Printf("Connecting to database %s at %s:%d as %s\n", dbConfig.Database, dbConfig.Host, dbConfig.Port, dbConfig.User)
|
log.Printf("Connecting to database %s at %s:%d as %s\n", dbConfig.Database, dbConfig.Host, dbConfig.Port, dbConfig.User)
|
||||||
|
|
||||||
tStart := time.Now()
|
var tStart time.Time = time.Now()
|
||||||
for i := range dbConfig.RetriesOnError {
|
for i := range dbConfig.RetriesOnError {
|
||||||
db, err = sql.Open("mysql", dbPath)
|
db, err = sql.Open("mysql", dbPath)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@ -568,6 +586,7 @@ func DecodeDatabaseResult(databaseResult *DatabaseResult) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
databaseResult.ParsedResult = map[string][]sql.NullString{}
|
databaseResult.ParsedResult = map[string][]sql.NullString{}
|
||||||
|
databaseResult.ParsedResultLength = 0
|
||||||
var numCol int = len(columns)
|
var numCol int = len(columns)
|
||||||
for _, c := range columns {
|
for _, c := range columns {
|
||||||
databaseResult.ParsedResult[c] = make([]sql.NullString, 0)
|
databaseResult.ParsedResult[c] = make([]sql.NullString, 0)
|
||||||
@ -586,6 +605,7 @@ func DecodeDatabaseResult(databaseResult *DatabaseResult) {
|
|||||||
for i, c := range columns {
|
for i, c := range columns {
|
||||||
databaseResult.ParsedResult[c] = append(databaseResult.ParsedResult[c], strArr[i])
|
databaseResult.ParsedResult[c] = append(databaseResult.ParsedResult[c], strArr[i])
|
||||||
}
|
}
|
||||||
|
databaseResult.ParsedResultLength++
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = rows.Err(); err != nil {
|
if err = rows.Err(); err != nil {
|
||||||
@ -1024,7 +1044,7 @@ func UpdateDatabaseStructure() {
|
|||||||
if i != 0 {
|
if i != 0 {
|
||||||
command += ", "
|
command += ", "
|
||||||
}
|
}
|
||||||
command += fmt.Sprintf("IN '%s' %s", pp.Name, pp.Type)
|
command += fmt.Sprintf("IN `%s` %s", pp.Name, pp.Type)
|
||||||
|
|
||||||
if ppc, ok := pp.Charset.(string); ok {
|
if ppc, ok := pp.Charset.(string); ok {
|
||||||
command += fmt.Sprintf(" CHARACTER SET %s", ppc)
|
command += fmt.Sprintf(" CHARACTER SET %s", ppc)
|
||||||
@ -1038,6 +1058,7 @@ func UpdateDatabaseStructure() {
|
|||||||
fmt.Println(command)
|
fmt.Println(command)
|
||||||
executeExec(command)
|
executeExec(command)
|
||||||
}
|
}
|
||||||
|
initDatabaseStructure()
|
||||||
}
|
}
|
||||||
|
|
||||||
func DestroyDatabase() {
|
func DestroyDatabase() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user