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"
|
||||
)
|
||||
|
||||
type apiUserDefinition struct {
|
||||
Id string
|
||||
Name string
|
||||
Permission string
|
||||
}
|
||||
|
||||
type apiHandleAdminFunction func(http.ResponseWriter, *http.Request, httprouter.Params, apiUserDefinition)
|
||||
|
||||
var apiRootPath string = "/api/v1"
|
||||
|
||||
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+"/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+"/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
|
||||
|
||||
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
|
||||
|
||||
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) {
|
||||
fmt.Fprintf(w, "API Auth Login")
|
||||
fmt.Fprintf(w, "API Auth Login\n")
|
||||
r.ParseForm()
|
||||
var username string = r.FormValue("username")
|
||||
var password string = r.FormValue("password")
|
||||
@ -118,7 +209,7 @@ func apiUser(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
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()
|
||||
var username string = params.ByName("name")
|
||||
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")
|
||||
w.(http.Flusher).Flush()
|
||||
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")
|
||||
}
|
||||
|
||||
@ -205,3 +299,30 @@ func setHeaderStream(w http.ResponseWriter) {
|
||||
w.Header().Set("Cache-Control", "no-cache")
|
||||
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 {
|
||||
Error DatabaseError
|
||||
SqlRows *sql.Rows
|
||||
SqlResult sql.Result
|
||||
ParsedResult map[string][]sql.NullString
|
||||
Error DatabaseError
|
||||
SqlRows *sql.Rows
|
||||
SqlResult sql.Result
|
||||
ParsedResultLength int64
|
||||
ParsedResult map[string][]sql.NullString
|
||||
}
|
||||
|
||||
const (
|
||||
@ -256,6 +257,16 @@ var databaseStructure databaseDefinition = databaseDefinition{
|
||||
Name: "user_id",
|
||||
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{
|
||||
// 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
|
||||
|
||||
{
|
||||
@ -380,6 +346,58 @@ var databaseStructure databaseDefinition = databaseDefinition{
|
||||
Name: "ListUsers",
|
||||
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{
|
||||
{
|
||||
@ -484,7 +502,7 @@ func connect() {
|
||||
var err error
|
||||
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 {
|
||||
db, err = sql.Open("mysql", dbPath)
|
||||
if err == nil {
|
||||
@ -568,6 +586,7 @@ func DecodeDatabaseResult(databaseResult *DatabaseResult) {
|
||||
}
|
||||
|
||||
databaseResult.ParsedResult = map[string][]sql.NullString{}
|
||||
databaseResult.ParsedResultLength = 0
|
||||
var numCol int = len(columns)
|
||||
for _, c := range columns {
|
||||
databaseResult.ParsedResult[c] = make([]sql.NullString, 0)
|
||||
@ -586,6 +605,7 @@ func DecodeDatabaseResult(databaseResult *DatabaseResult) {
|
||||
for i, c := range columns {
|
||||
databaseResult.ParsedResult[c] = append(databaseResult.ParsedResult[c], strArr[i])
|
||||
}
|
||||
databaseResult.ParsedResultLength++
|
||||
}
|
||||
|
||||
if err = rows.Err(); err != nil {
|
||||
@ -1024,7 +1044,7 @@ func UpdateDatabaseStructure() {
|
||||
if i != 0 {
|
||||
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 {
|
||||
command += fmt.Sprintf(" CHARACTER SET %s", ppc)
|
||||
@ -1038,6 +1058,7 @@ func UpdateDatabaseStructure() {
|
||||
fmt.Println(command)
|
||||
executeExec(command)
|
||||
}
|
||||
initDatabaseStructure()
|
||||
}
|
||||
|
||||
func DestroyDatabase() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user