Explorar el Código

Added basic structure for arsamba

TC pushbot 5 hace 4 años
padre
commit
f32cb4c779
Se han modificado 14 ficheros con 609 adiciones y 0 borrados
  1. 0 0
      .disabled
  2. 70 0
      aroz/aroz.go
  3. BIN
      aroz/doc.txt
  4. 31 0
      build.bat
  5. 18 0
      build.sh
  6. 222 0
      common.go
  7. 3 0
      go.mod
  8. 125 0
      main.go
  9. BIN
      web/img/desktop_icon.png
  10. BIN
      web/img/desktop_icon.psd
  11. BIN
      web/img/icon.png
  12. BIN
      web/img/icon.psd
  13. BIN
      web/img/samba.png
  14. 140 0
      web/index.html

+ 0 - 0
.disabled


+ 70 - 0
aroz/aroz.go

@@ -0,0 +1,70 @@
+package aroz
+
+import (
+	"flag"
+	"fmt"
+	"net/http"
+	"net/url"
+	"encoding/json"
+	"os"
+)
+
+type ArozHandler struct{
+	Port string
+	restfulEndpoint string
+}
+
+//Information required for registering this subservice to arozos
+type ServiceInfo struct{
+	Name string				//Name of this module. e.g. "Audio"
+	Desc string				//Description for this module
+	Group string			//Group of the module, e.g. "system" / "media" etc
+	IconPath string			//Module icon image path e.g. "Audio/img/function_icon.png"
+	Version string			//Version of the module. Format: [0-9]*.[0-9][0-9].[0-9]
+	StartDir string 		//Default starting dir, e.g. "Audio/index.html"
+	SupportFW bool 			//Support floatWindow. If yes, floatWindow dir will be loaded
+	LaunchFWDir string 		//This link will be launched instead of 'StartDir' if fw mode
+	SupportEmb bool			//Support embedded mode
+	LaunchEmb string 		//This link will be launched instead of StartDir / Fw if a file is opened with this module
+	InitFWSize []int 		//Floatwindow init size. [0] => Width, [1] => Height
+	InitEmbSize []int		//Embedded mode init size. [0] => Width, [1] => Height
+	SupportedExt []string 	//Supported File Extensions. e.g. ".mp3", ".flac", ".wav"
+}
+
+//This function will request the required flag from the startup paramters and parse it to the need of the arozos.
+func HandleFlagParse(info ServiceInfo) *ArozHandler{
+	var infoRequestMode = flag.Bool("info", false, "Show information about this subservice")
+	var port = flag.String("port", ":80", "The default listening endpoint for this subservice")
+	var restful = flag.String("rpt", "http://localhost:8080/api/ajgi/interface", "The RESTFUL Endpoint of the parent")
+	//Parse the flags
+	flag.Parse();
+	if (*infoRequestMode == true){
+		//Information request mode
+		jsonString, _ := json.Marshal(info);
+		fmt.Println(string(jsonString))
+		os.Exit(0);
+	}
+	return &ArozHandler{
+		Port: *port,
+		restfulEndpoint: *restful,
+	};
+}
+
+//Get the username and resources access token from the request, return username, token
+func (a *ArozHandler)GetUserInfoFromRequest(w http.ResponseWriter, r *http.Request)(string, string){
+	username := r.Header.Get("aouser")
+	token := r.Header.Get("aotoken")
+
+	return username, token
+}
+
+func (a *ArozHandler)RequestGatewayInterface(token string, script string)(*http.Response, error){
+	resp, err := http.PostForm(a.restfulEndpoint,
+		url.Values{"token":{token}, "script":{script}})
+    if err != nil {
+		// handle error
+		return nil, err
+	}
+	
+	return resp, nil
+}

BIN
aroz/doc.txt


+ 31 - 0
build.bat

@@ -0,0 +1,31 @@
+echo "Building darwin"
+set GOOS=darwin
+set GOARCH=amd64
+
+for %%I in (.) do SET EXENAME=%%~nxI
+
+go build
+MOVE "%EXENAME%" "%EXENAME%_darwin_amd64"
+
+echo "Building linux"
+set GOOS=linux
+set GOARCH=amd64
+go build
+MOVE "%EXENAME%" "%EXENAME%_linux_amd64"
+
+set GOOS=linux
+set GOARCH=arm
+go build
+MOVE "%EXENAME%" "%EXENAME%_linux_arm"
+
+set GOOS=linux
+set GOARCH=arm64
+go build
+MOVE "%EXENAME%" "%EXENAME%_linux_arm64"
+
+echo "Building windows"
+set GOOS=windows
+set GOARCH=amd64
+go build
+
+echo "Completed"

+ 18 - 0
build.sh

@@ -0,0 +1,18 @@
+# /bin/sh
+echo "Building darwin"
+GOOS=darwin GOARCH=amd64 go build
+mv "${PWD##*/}" "${PWD##*/}_darwin_amd64"
+
+echo "Building linux"
+GOOS=linux GOARCH=amd64 go build
+mv "${PWD##*/}" "${PWD##*/}_linux_amd64"
+GOOS=linux GOARCH=arm go build
+mv "${PWD##*/}" "${PWD##*/}_linux_arm"
+GOOS=linux GOARCH=arm64 go build
+mv "${PWD##*/}" "${PWD##*/}_linux_arm64"
+
+echo "Building windows"
+GOOS=windows GOARCH=amd64 go build
+
+
+echo "Completed"

+ 222 - 0
common.go

@@ -0,0 +1,222 @@
+package main
+
+import (
+	"os"
+    "log"
+	"net/http"
+	"strconv"
+	"strings"
+	"errors"
+	"encoding/base64"
+	"bufio"
+	"io/ioutil"
+	"time"
+)
+
+/*
+	SYSTEM COMMON FUNCTIONS
+
+	This is a system function that put those we usually use function but not belongs to
+	any module / system.
+
+	E.g. fileExists / IsDir etc
+
+*/
+
+/*
+	Basic Response Functions
+
+	Send response with ease
+*/
+//Send text response with given w and message as string
+func sendTextResponse(w http.ResponseWriter, msg string) {
+	w.Write([]byte(msg))
+}
+
+//Send JSON response, with an extra json header
+func sendJSONResponse(w http.ResponseWriter, json string) {
+	w.Header().Set("Content-Type", "application/json")
+	w.Write([]byte(json))
+}
+
+func sendErrorResponse(w http.ResponseWriter, errMsg string) {
+	w.Header().Set("Content-Type", "application/json")
+	w.Write([]byte("{\"error\":\"" + errMsg + "\"}"))
+}
+
+func sendOK(w http.ResponseWriter) {
+	w.Header().Set("Content-Type", "application/json")
+	w.Write([]byte("\"OK\""))
+}
+/*
+	The paramter move function (mv)
+
+	You can find similar things in the PHP version of ArOZ Online Beta. You need to pass in
+	r (HTTP Request Object)
+	getParamter (string, aka $_GET['This string])
+
+	Will return
+	Paramter string (if any)
+	Error (if error)
+
+*/
+func mv(r *http.Request, getParamter string, postMode bool) (string, error) {
+	if postMode == false {
+		//Access the paramter via GET
+		keys, ok := r.URL.Query()[getParamter]
+
+		if !ok || len(keys[0]) < 1 {
+			//log.Println("Url Param " + getParamter +" is missing")
+			return "", errors.New("GET paramter " + getParamter + " not found or it is empty")
+		}
+
+		// Query()["key"] will return an array of items,
+		// we only want the single item.
+		key := keys[0]
+		return string(key), nil
+	} else {
+		//Access the parameter via POST
+		r.ParseForm()
+		x := r.Form.Get(getParamter)
+		if len(x) == 0 || x == "" {
+			return "", errors.New("POST paramter " + getParamter + " not found or it is empty")
+		}
+		return string(x), nil
+	}
+
+}
+
+func stringInSlice(a string, list []string) bool {
+    for _, b := range list {
+        if b == a {
+            return true
+        }
+    }
+    return false
+}
+
+
+func fileExists(filename string) bool {
+    _, err := os.Stat(filename)
+    if os.IsNotExist(err) {
+        return false
+    }
+    return true
+}
+
+
+func IsDir(path string) bool{
+	if (fileExists(path) == false){
+		return false
+	}
+	fi, err := os.Stat(path)
+    if err != nil {
+        log.Fatal(err)
+        return false
+    }
+    switch mode := fi.Mode(); {
+    case mode.IsDir():
+        return true
+    case mode.IsRegular():
+        return false
+	}
+	return false
+}
+
+func inArray(arr []string, str string) bool {
+	for _, a := range arr {
+	   if a == str {
+		  return true
+	   }
+	}
+	return false
+ }
+
+ func timeToString(targetTime time.Time) string{
+	 return targetTime.Format("2006-01-02 15:04:05")
+ }
+
+ func IntToString(number int) string{
+	return strconv.Itoa(number)
+ }
+
+ func StringToInt(number string) (int, error){
+	return strconv.Atoi(number)
+ }
+
+ func StringToInt64(number string) (int64, error){
+	i, err := strconv.ParseInt(number, 10, 64)
+	if err != nil {
+		return -1, err
+	}
+	return i, nil
+ }
+
+ func Int64ToString(number int64) string{
+	convedNumber:=strconv.FormatInt(number,10)
+	return convedNumber
+ }
+
+ func GetUnixTime() int64{
+	return time.Now().Unix()
+ }
+
+ func LoadImageAsBase64(filepath string) (string, error){
+	if !fileExists(filepath){
+		return "", errors.New("File not exists")
+	}
+	f, _ := os.Open(filepath)
+    reader := bufio.NewReader(f)
+    content, _ := ioutil.ReadAll(reader)
+	encoded := base64.StdEncoding.EncodeToString(content)
+	return string(encoded), nil
+ }
+
+ func PushToSliceIfNotExist(slice []string, newItem string) []string {
+	itemExists := false
+	for _, item := range slice{
+		if item == newItem{
+			itemExists = true
+		}
+	}
+
+	if !itemExists{
+		slice = append(slice, newItem)
+	}
+
+	return slice
+ }
+
+ func RemoveFromSliceIfExists(slice []string, target string) []string {
+	 newSlice := []string{}
+	 for _, item := range slice{
+		 if item != target{
+			newSlice = append(newSlice, item)
+		 }
+	 }
+
+	 return newSlice;
+ }
+
+ //Get the IP address of the current authentication user
+func ReflectUserIP(w http.ResponseWriter, r *http.Request) {
+    requestPort,_ :=  mv(r, "port", false)
+    showPort := false;
+    if (requestPort == "true"){
+        //Show port as well
+        showPort = true;
+    }
+    IPAddress := r.Header.Get("X-Real-Ip")
+    if IPAddress == "" {
+        IPAddress = r.Header.Get("X-Forwarded-For")
+    }
+    if IPAddress == "" {
+        IPAddress = r.RemoteAddr
+    }
+    if (!showPort){
+        IPAddress = IPAddress[:strings.LastIndex(IPAddress, ":")]
+
+    }
+    w.Write([]byte(IPAddress))
+    return;
+}

+ 3 - 0
go.mod

@@ -0,0 +1,3 @@
+module git.arozos.com/ArSamba
+
+go 1.14

+ 125 - 0
main.go

@@ -0,0 +1,125 @@
+package main
+
+import (
+	"encoding/json"
+	"log"
+	"net/http"
+	"os"
+	"os/signal"
+	"syscall"
+
+	"git.arozos.com/ArSamba/aroz"
+)
+
+var (
+	handler *aroz.ArozHandler
+)
+
+func SetupCloseHandler() {
+	c := make(chan os.Signal, 2)
+	signal.Notify(c, os.Interrupt, syscall.SIGTERM)
+	go func() {
+		<-c
+		log.Println("\r- Shutting down ArSamba module.")
+
+		os.Exit(0)
+	}()
+}
+
+func main() {
+	//If you have other flags, please add them here
+
+	//Start the aoModule pipeline (which will parse the flags as well). Pass in the module launch information
+	handler = aroz.HandleFlagParse(aroz.ServiceInfo{
+		Name:        "ArSamba",
+		Desc:        "arozos Samba Setting Subservice",
+		Group:       "System Settings",
+		IconPath:    "arsamba/img/icon.png",
+		Version:     "1.0",
+		StartDir:    "arsamba/index.html",
+		SupportFW:   true,
+		LaunchFWDir: "arsamba/index.html",
+		InitFWSize:  []int{350, 560},
+	})
+
+	//Register the standard web services urls
+	fs := http.FileServer(http.Dir("./web"))
+	http.HandleFunc("/create", handleNewUser)
+	http.HandleFunc("/remove", handleUserRemove)
+	http.HandleFunc("/getStatus", handleGetStatus)
+	http.Handle("/", fs)
+
+	SetupCloseHandler()
+
+	log.Println("ArSamba subservice started. Listening on " + handler.Port)
+	err := http.ListenAndServe(handler.Port, nil)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+}
+
+func handleGetStatus(w http.ResponseWriter, r *http.Request) {
+	username, err := mv(r, "username", false)
+	if err != nil {
+		sendErrorResponse(w, "Invalid username given")
+		return
+	}
+	//Check if the user has already in samba user
+	log.Println("Checking User Status", username)
+
+	//Send the results
+	js, _ := json.Marshal(true)
+	sendJSONResponse(w, string(js))
+}
+
+func handleNewUser(w http.ResponseWriter, r *http.Request) {
+	//Get the required information
+	username, err := mv(r, "username", true)
+	if err != nil {
+		sendErrorResponse(w, "Invalid username given")
+		return
+	}
+
+	//Match the session username
+	proxyUser, _ := handler.GetUserInfoFromRequest(w, r)
+	if username != proxyUser {
+		sendErrorResponse(w, "User not logged in")
+		return
+	}
+
+	password, err := mv(r, "password", true)
+	if err != nil {
+		sendErrorResponse(w, "Invalid password given")
+		return
+	}
+
+	//Add the user to samba
+	log.Println("Adding User", username, password)
+
+	//Return ok
+	sendOK(w)
+
+}
+
+func handleUserRemove(w http.ResponseWriter, r *http.Request) {
+	//Get the required information
+	username, err := mv(r, "username", true)
+	if err != nil {
+		sendErrorResponse(w, "Invalid username given")
+		return
+	}
+
+	//Match the session username
+	proxyUser, _ := handler.GetUserInfoFromRequest(w, r)
+	if username != proxyUser {
+		sendErrorResponse(w, "User not logged in")
+		return
+	}
+
+	//OK! Remove user
+	log.Println("Remove user", username)
+
+	//Return OK
+	sendOK(w)
+}

BIN
web/img/desktop_icon.png


BIN
web/img/desktop_icon.psd


BIN
web/img/icon.png


BIN
web/img/icon.psd


BIN
web/img/samba.png


+ 140 - 0
web/index.html

@@ -0,0 +1,140 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta name="apple-mobile-web-app-capable" content="yes" />
+        <meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1"/>
+        <meta charset="UTF-8">
+        <meta name="theme-color" content="#4b75ff">
+        <link rel="stylesheet" href="../script/semantic/semantic.min.css">
+        <script src="../script/jquery.min.js"></script>
+        <script src="../script/ao_module.js"></script>
+        <script src="../script/semantic/semantic.min.js"></script>
+        <title>ArSamba Settings</title>
+        <style>
+            body{
+                background-color:white;
+            }
+
+            .success{
+                color: #20c942;
+            }
+
+            .failed{
+                color: #eb4034;
+            }
+        </style>
+    </head>
+    <body>
+        <br>
+		<div class="ui text container">
+            <div class="ui header">
+                <i class="windows icon"></i>
+                <div class="content">
+                    Samba Settings
+                    <div class="sub header">for arozos systems</div>
+                </div>
+            </div>
+            <p>Account Status: <span id="acstatus" class="failed">Disabled</span></p>
+            <div id="enableAccount">
+                <h3>Enable My Samba Account</h3>
+                <form class="ui form" onsubmit="createAccount(event);">
+                <div class="fluid field">
+                    <label>Username (Read Only)</label>
+                    <input type="text" id="username" readonly="true">
+                </div>
+                <div class="field">
+                    <label>Password</label>
+                    <input type="password" id="pw">
+                </div>
+                <div class="field">
+                    <label>Confirm Password</label>
+                    <input type="password" id="rpw">
+                </div>
+                <button class="ui green button" type="submit">Create</button>
+                </form>
+            </div>
+            <div id="disableAccount" style="display:none;">
+                <h3>Disable My Samba Account</h3>
+                <p>This operation will remove your samba user account from the system</p>
+                <button class="ui red button" onclick="removeUser(event)">Disable</button>
+            </div>
+            
+        <br><br>
+        <script>
+            //Do not allow window resize
+            ao_module_setFixedWindowSize();
+
+            //Get username from system
+            $.get("../system/users/userinfo", function(data){
+                var username = data.Username;
+                $("#username").val(username);
+
+                //Get the account status
+                $.get("./getStatus?username=" + username, function(data){
+                    if (data == true){
+                        $("#acstatus").text("Enabled");
+                        $("#acstatus").attr("class","success");
+                        $("#enableAccount").hide();
+                        $("#disableAccount").show();
+                    } else{
+                        $("#acstatus").text("Disabled");
+                        $("#acstatus").attr("class","failed");
+                        $("#enableAccount").show();
+                        $("#disableAccount").hide();
+                    }
+                });
+            });
+
+            function removeUser(e){
+                 //Process the user creation process
+                 $.get("../system/users/userinfo", function(data){
+                    //Get the username
+                    var username = data.Username;
+                    $.ajax({
+                        url: "./remove",
+                        method: "POST",
+                        data: {username: username},
+                        success: function(data){
+                            //Creation succeed. Reload this page
+                            window.location.reload();
+                        }
+                    });
+                 });
+                
+            }
+            
+
+            function createAccount(e){
+                e.preventDefault();
+                //Get the userinfo again in case the user has changed name during the setting period
+                $.get("../system/users/userinfo", function(data){
+                    //Get the username
+                    var username = data.Username;
+                    
+                    //Check if the password match
+                    var pw = $("#pw").val();
+                    var rpw = $("#rpw").val();
+                    if (pw != rpw){
+                        //Password not match
+                        $("#rpw").parent().addClass("error");
+                        return
+                    }else{
+                        $("#rpw").parent().removeClass("error");
+                    }
+
+                    //Process the user creation process
+                    $.ajax({
+                        url: "./create",
+                        method: "POST",
+                        data: {username: username, password: pw},
+                        success: function(data){
+                            //Creation succeed. Reload this page
+                            window.location.reload();
+                        }
+                    });
+
+                });
+            }
+        </script>
+    </body>
+</html>