]> git.feebdaed.xyz Git - lgtm-rsvp.git/commitdiff
ready all apis
authorseantywork <seantywork@gmail.com>
Sat, 4 Jan 2025 05:46:12 +0000 (05:46 +0000)
committerseantywork <seantywork@gmail.com>
Sat, 4 Jan 2025 05:46:12 +0000 (05:46 +0000)
14 files changed:
pkg/auth/auth_idpw.go [deleted file]
pkg/auth/auth_oauth2.go
pkg/auth/auth_session.go
pkg/auth/auth_verify.go
pkg/db/db_media.go
pkg/db/db_story.go
pkg/db/db_story_etc.go [new file with mode: 0644]
pkg/server/api/api.go
pkg/server/api/api_auth.go [new file with mode: 0644]
pkg/server/api/api_story.go [new file with mode: 0644]
pkg/server/server.go
pkg/server/server_view.go
public/js/story/write.js
view/read.html

diff --git a/pkg/auth/auth_idpw.go b/pkg/auth/auth_idpw.go
deleted file mode 100644 (file)
index 8832b06..0000000
+++ /dev/null
@@ -1 +0,0 @@
-package auth
index a97fc93f3e9eee1df9be002c8a10503832f0f64c..2f542f3a5a23226e449bb588b810214099bef6ff 100644 (file)
@@ -5,6 +5,7 @@ import (
        "encoding/json"
        "fmt"
        "io"
+       "log"
        "net/http"
        "os"
 
@@ -86,7 +87,7 @@ func GenerateGoogleOauthConfig() *oauth2.Config {
                google_oauth_config.RedirectURL = OAUTH_JSON.Web.RedirectUris[1]
        }
 
-       fmt.Println(google_oauth_config.RedirectURL)
+       log.Println(google_oauth_config.RedirectURL)
 
        return google_oauth_config
 
index 76728d648746503ff907ff96cd5ab48704215585..31dea8b384f2f0cf9aad69fc1de409b546e98584 100644 (file)
@@ -8,7 +8,7 @@ import (
        "github.com/gin-gonic/gin"
 )
 
-func Is0(c *gin.Context) bool {
+func Is0(c *gin.Context, userId *string, sessionId *string) bool {
 
        session := sessions.Default(c)
 
@@ -40,5 +40,14 @@ func Is0(c *gin.Context) bool {
                return false
        }
 
+       if userId != nil {
+               *userId = s.Id
+       }
+
+       if sessionId != nil {
+
+               *sessionId = session_id
+       }
+
        return true
 }
index 07710fc31cffaec757aad69cc65f31a94ca8efc4..8ffac8dc32e61a14f54d056760905036b20c7c91 100644 (file)
@@ -5,10 +5,38 @@ import (
        "unicode"
 )
 
+func VerifyDefaultValue(raw string) bool {
+
+       for _, c := range raw {
+
+               if unicode.IsLower(c) {
+
+                       continue
+
+               } else if unicode.IsDigit(c) {
+
+                       continue
+
+               } else if c == '-' {
+
+               } else {
+
+                       return false
+               }
+
+       }
+
+       return true
+}
+
 func VerifyMediaKey(mediakey string) bool {
 
        mklist := strings.SplitN(mediakey, ".", 2)
 
+       if len(mklist) != 2 {
+               return false
+       }
+
        for _, c := range mklist[0] {
 
                if unicode.IsLetter(c) {
index 771cccd84b053d11b7bd858b83ec36f61dec1e06..ae00bbac1b52d897195c49de40b2cbe9cb74dd22 100644 (file)
@@ -1,11 +1,9 @@
 package db
 
 import (
-       "encoding/json"
        "fmt"
        "mime/multipart"
        "os"
-       "strings"
 
        "github.com/gin-gonic/gin"
 )
@@ -54,82 +52,3 @@ func DeleteMedia(media_key string) error {
 
        return nil
 }
-
-func GetAssociateMediaKeysForEditorjsSrc(rawContent string) ([]string, error) {
-
-       var retlist []string
-
-       var editorjsSrc map[string]interface{}
-
-       rawContentBytes := []byte(rawContent)
-
-       err := json.Unmarshal(rawContentBytes, &editorjsSrc)
-
-       if err != nil {
-
-               return nil, fmt.Errorf("failed to unmarshal: %s", err.Error())
-
-       }
-
-       blocks, okay := editorjsSrc["blocks"]
-
-       if !okay {
-
-               return nil, fmt.Errorf("invalid format: %s", "no blocks")
-       }
-
-       blocksList := blocks.([]interface{})
-
-       blocksLen := len(blocksList)
-
-       for i := 0; i < blocksLen; i++ {
-
-               blockObj := blocksList[i].(map[string]interface{})
-
-               objType, okay := blockObj["type"]
-
-               if !okay {
-                       continue
-               }
-
-               if objType != "image" {
-                       continue
-               }
-
-               objData, okay := blockObj["data"]
-
-               if !okay {
-                       continue
-               }
-
-               objFields := objData.(map[string]interface{})
-
-               fileField, okay := objFields["file"]
-
-               if !okay {
-                       continue
-               }
-
-               targetProps := fileField.(map[string]interface{})
-
-               urlTarget, okay := targetProps["url"]
-
-               if !okay {
-                       continue
-               }
-
-               target := urlTarget.(string)
-
-               pathList := strings.Split(target, "/")
-
-               keyExt := pathList[len(pathList)-1]
-
-               keyExtList := strings.Split(keyExt, ".")
-
-               key := keyExtList[0]
-
-               retlist = append(retlist, key)
-       }
-
-       return retlist, nil
-}
index 6b794ca9e539a67b306bbdc14bff404edd0895a9..fc0293ab17de34dc23d8aaecd6bf0b5398d780ff 100644 (file)
@@ -1,6 +1,9 @@
 package db
 
-import "fmt"
+import (
+       "fmt"
+       "log"
+)
 
 type Story struct {
        StoryId          int
@@ -168,13 +171,20 @@ func GetStoryByTitle(title string) (*Story, error) {
 
 }
 
-func DeleteStoryByTitle(title string) (*Story, error) {
+func DeleteStoryById(id string) error {
 
-       story, err := GetStoryByTitle(title)
+       story, err := GetStoryById(id)
 
        if err != nil {
 
-               return nil, fmt.Errorf("failed to get story by title")
+               return fmt.Errorf("failed to get story by id")
+       }
+
+       keys, err := GetAssociateMediaKeysForEditorjsSrc([]byte(story.Content))
+
+       if err != nil {
+
+               return fmt.Errorf("failed to get story media keys by id: %v", err)
        }
 
        q := `
@@ -193,9 +203,69 @@ func DeleteStoryByTitle(title string) (*Story, error) {
        err = exec(q, a)
 
        if err != nil {
-               return nil, fmt.Errorf("failed to delete story record")
+               return fmt.Errorf("failed to delete story record")
+       }
+
+       keysLen := len(keys)
+
+       for i := 0; i < keysLen; i++ {
+
+               err = DeleteMedia(keys[i])
+
+               if err != nil {
+
+                       log.Printf("failed to delete media key: %s\n", err.Error())
+               }
+
+       }
+
+       return nil
+
+}
+
+func GetAllStory() ([]Story, error) {
+
+       stories := []Story{}
+
+       q := `
+       
+       SELECT 
+               *
+       FROM
+               story
+       `
+
+       a := []any{}
+
+       res, err := query(q, a)
+
+       if err != nil {
+
+               return nil, fmt.Errorf("failed to get all story: %v", err)
+       }
+
+       defer res.Close()
+
+       for res.Next() {
+
+               story := Story{}
+
+               err = res.Scan(
+
+                       &story.Id,
+                       &story.Title,
+                       &story.DateMarked,
+                       &story.PrimaryMediaName,
+               )
+
+               if err != nil {
+                       return nil, fmt.Errorf("failed to get story record: %v", err)
+               }
+
+               stories = append(stories, story)
+
        }
 
-       return story, nil
+       return stories, nil
 
 }
diff --git a/pkg/db/db_story_etc.go b/pkg/db/db_story_etc.go
new file mode 100644 (file)
index 0000000..b0897d9
--- /dev/null
@@ -0,0 +1,80 @@
+package db
+
+import (
+       "encoding/json"
+       "fmt"
+       "strings"
+)
+
+func GetAssociateMediaKeysForEditorjsSrc(rawArticle []byte) ([]string, error) {
+
+       var retlist []string
+
+       var editorjsSrc map[string]interface{}
+
+       err := json.Unmarshal(rawArticle, &editorjsSrc)
+
+       if err != nil {
+
+               return nil, fmt.Errorf("failed to unmarshal: %s", err.Error())
+
+       }
+
+       blocks, okay := editorjsSrc["blocks"]
+
+       if !okay {
+
+               return nil, fmt.Errorf("invalid format: %s", "no blocks")
+       }
+
+       blocksList := blocks.([]interface{})
+
+       blocksLen := len(blocksList)
+
+       for i := 0; i < blocksLen; i++ {
+
+               blockObj := blocksList[i].(map[string]interface{})
+
+               objType, okay := blockObj["type"]
+
+               if !okay {
+                       continue
+               }
+
+               if objType != "image" {
+                       continue
+               }
+
+               objData, okay := blockObj["data"]
+
+               if !okay {
+                       continue
+               }
+
+               objFields := objData.(map[string]interface{})
+
+               fileField, okay := objFields["file"]
+
+               if !okay {
+                       continue
+               }
+
+               targetProps := fileField.(map[string]interface{})
+
+               urlTarget, okay := targetProps["url"]
+
+               if !okay {
+                       continue
+               }
+
+               target := urlTarget.(string)
+
+               pathList := strings.Split(target, "/")
+
+               key := pathList[len(pathList)-1]
+
+               retlist = append(retlist, key)
+       }
+
+       return retlist, nil
+}
index 9fb19e71c1bf9972f40938b9dc742f3461ed8f6c..81c52042c327a83ccaccf001608a2765ff6910eb 100644 (file)
@@ -1,18 +1,5 @@
 package api
 
-import (
-       "encoding/json"
-       "fmt"
-       "log"
-       "net/http"
-
-       pkgauth "our-wedding-rsvp/pkg/auth"
-       pkgdb "our-wedding-rsvp/pkg/db"
-
-       "github.com/gin-gonic/contrib/sessions"
-       "github.com/gin-gonic/gin"
-)
-
 type CLIENT_REQ struct {
        Data string `json:"data"`
 }
@@ -21,120 +8,3 @@ type SERVER_RESP struct {
        Status string `json:"status"`
        Reply  string `json:"reply"`
 }
-
-func OauthGoogleLogin(c *gin.Context) {
-
-       if pkgauth.Is0(c) {
-
-               log.Printf("oauth login: already logged in\n")
-
-               c.JSON(http.StatusBadRequest, SERVER_RESP{Status: "error", Reply: "already logged in"})
-
-               return
-
-       }
-
-       oauth_state := pkgauth.GenerateStateAuthCookie(c)
-
-       u := pkgauth.GoogleOauthConfig.AuthCodeURL(oauth_state)
-
-       c.Redirect(302, u)
-
-}
-
-func OauthGoogleCallback(c *gin.Context) {
-
-       if pkgauth.Is0(c) {
-
-               fmt.Printf("oauth callback: already logged in\n")
-
-               c.JSON(http.StatusBadRequest, SERVER_RESP{Status: "error", Reply: "already logged in"})
-
-               return
-
-       }
-
-       session := sessions.Default(c)
-
-       var session_id string
-
-       v := session.Get("RSVP")
-
-       if v == nil {
-               log.Printf("access auth failed: %s\n", "session id not found")
-               return
-       } else {
-               session_id = v.(string)
-       }
-
-       state := c.Request.FormValue("state")
-
-       if state == "" {
-               log.Printf("access auth failed: %s\n", "form state not found")
-               return
-       }
-
-       if state != session_id {
-               log.Printf("access auth failed: %s\n", "value not matching")
-               c.Redirect(302, "/")
-               return
-       }
-
-       data, err := pkgauth.GetUserDataFromGoogle(c.Request.FormValue("code"))
-       if err != nil {
-               log.Printf("access auth failed: %s\n", err.Error())
-               c.Redirect(302, "/")
-               return
-       }
-
-       var oauth_struct pkgauth.OAuthStruct
-
-       err = json.Unmarshal(data, &oauth_struct)
-
-       if err != nil {
-               log.Printf("access auth failed: %s\n", err.Error())
-               c.Redirect(302, "/")
-               return
-       }
-
-       if !oauth_struct.VERIFIED_EMAIL {
-               log.Printf("access auth failed: %s\n", err.Error())
-               c.Redirect(302, "/")
-               return
-       }
-
-       if err != nil {
-               log.Printf("access auth failed: %s\n", err.Error())
-               c.Redirect(302, "/")
-               return
-       }
-
-       as, err := pkgdb.GetAdminById(oauth_struct.EMAIL)
-
-       if as == nil {
-
-               log.Printf("access auth failed: %s", err.Error())
-
-               c.Redirect(302, "/")
-
-               return
-
-       }
-
-       err = pkgdb.SetAdminSessionId(oauth_struct.EMAIL, session_id, true)
-
-       if err != nil {
-
-               log.Printf("make session failed for admin: %s", err.Error())
-
-               c.Redirect(302, "/")
-
-               return
-
-       }
-
-       log.Println("oauth sign in success")
-
-       c.Redirect(302, "/")
-
-}
diff --git a/pkg/server/api/api_auth.go b/pkg/server/api/api_auth.go
new file mode 100644 (file)
index 0000000..9c86e01
--- /dev/null
@@ -0,0 +1,226 @@
+package api
+
+import (
+       "encoding/json"
+       "log"
+       "net/http"
+
+       pkgauth "our-wedding-rsvp/pkg/auth"
+       pkgdb "our-wedding-rsvp/pkg/db"
+
+       "github.com/gin-gonic/contrib/sessions"
+       "github.com/gin-gonic/gin"
+)
+
+type UserLogin struct {
+       Id         string `json:"id"`
+       Passphrase string `json:"passphrase"`
+}
+
+func OauthGoogleLogin(c *gin.Context) {
+
+       if pkgauth.Is0(c, nil, nil) {
+
+               log.Printf("oauth login: already logged in\n")
+
+               c.JSON(http.StatusBadRequest, SERVER_RESP{Status: "error", Reply: "already logged in"})
+
+               return
+
+       }
+
+       oauth_state := pkgauth.GenerateStateAuthCookie(c)
+
+       u := pkgauth.GoogleOauthConfig.AuthCodeURL(oauth_state)
+
+       c.Redirect(302, u)
+
+}
+
+func OauthGoogleCallback(c *gin.Context) {
+
+       if pkgauth.Is0(c, nil, nil) {
+
+               log.Printf("oauth callback: already logged in\n")
+
+               c.JSON(http.StatusBadRequest, SERVER_RESP{Status: "error", Reply: "already logged in"})
+
+               return
+
+       }
+
+       session := sessions.Default(c)
+
+       var session_id string
+
+       v := session.Get("RSVP")
+
+       if v == nil {
+               log.Printf("access auth failed: %s\n", "session id not found")
+               return
+       } else {
+               session_id = v.(string)
+       }
+
+       state := c.Request.FormValue("state")
+
+       if state == "" {
+               log.Printf("access auth failed: %s\n", "form state not found")
+               return
+       }
+
+       if state != session_id {
+               log.Printf("access auth failed: %s\n", "value not matching")
+               c.Redirect(302, "/")
+               return
+       }
+
+       data, err := pkgauth.GetUserDataFromGoogle(c.Request.FormValue("code"))
+       if err != nil {
+               log.Printf("access auth failed: %s\n", err.Error())
+               c.Redirect(302, "/")
+               return
+       }
+
+       var oauth_struct pkgauth.OAuthStruct
+
+       err = json.Unmarshal(data, &oauth_struct)
+
+       if err != nil {
+               log.Printf("access auth failed: %s\n", err.Error())
+               c.Redirect(302, "/")
+               return
+       }
+
+       if !oauth_struct.VERIFIED_EMAIL {
+               log.Printf("access auth failed: %s\n", err.Error())
+               c.Redirect(302, "/")
+               return
+       }
+
+       if err != nil {
+               log.Printf("access auth failed: %s\n", err.Error())
+               c.Redirect(302, "/")
+               return
+       }
+
+       as, err := pkgdb.GetAdminById(oauth_struct.EMAIL)
+
+       if as == nil {
+
+               log.Printf("access auth failed: %s", err.Error())
+
+               c.Redirect(302, "/")
+
+               return
+
+       }
+
+       err = pkgdb.SetAdminSessionId(oauth_struct.EMAIL, session_id, true)
+
+       if err != nil {
+
+               log.Printf("make session failed for admin: %s", err.Error())
+
+               c.Redirect(302, "/")
+
+               return
+
+       }
+
+       log.Println("oauth sign in success")
+
+       c.Redirect(302, "/")
+
+}
+
+func Login(c *gin.Context) {
+
+       if pkgauth.USE_OAUTH2 {
+               log.Printf("user login: use oauth2\n")
+
+               c.JSON(http.StatusBadRequest, SERVER_RESP{Status: "error", Reply: "invalid"})
+
+               return
+       }
+
+       var req CLIENT_REQ
+
+       var u_login UserLogin
+
+       if err := c.BindJSON(&req); err != nil {
+
+               log.Printf("user login: failed to bind: %s\n", err.Error())
+
+               c.JSON(http.StatusBadRequest, SERVER_RESP{Status: "error", Reply: "invalid format"})
+
+               return
+       }
+
+       err := json.Unmarshal([]byte(req.Data), &u_login)
+
+       if err != nil {
+
+               log.Printf("user login: failed to unmarshal: %s\n", err.Error())
+
+               c.JSON(http.StatusBadRequest, SERVER_RESP{Status: "error", Reply: "invalid format"})
+
+               return
+
+       }
+
+       if !pkgauth.VerifyDefaultValue(u_login.Id) {
+
+               log.Printf("user login: not valid id: %s\n", u_login.Id)
+
+               c.JSON(http.StatusBadRequest, SERVER_RESP{Status: "error", Reply: "invalid format"})
+
+               return
+       }
+
+       us, err := pkgdb.GetAdminById(u_login.Id)
+
+       if err != nil {
+
+               log.Printf("user login: failed to get from user: %s\n", err.Error())
+
+               c.JSON(http.StatusForbidden, SERVER_RESP{Status: "error", Reply: "id doesn't exist"})
+
+               return
+       }
+
+       if !us.Pw.Valid {
+               log.Printf("user login: failed to get admin pw: null\n")
+
+               c.JSON(http.StatusForbidden, SERVER_RESP{Status: "error", Reply: "id invalid"})
+
+               return
+       }
+
+       if us.Pw.String != u_login.Passphrase {
+
+               log.Printf("user login: passphrase: %s", "not matching")
+
+               c.JSON(http.StatusForbidden, SERVER_RESP{Status: "error", Reply: "passphrase not matching"})
+
+               return
+
+       }
+
+       session_key := pkgauth.GenerateStateAuthCookie(c)
+
+       err = pkgdb.SetAdminSessionId(us.Id, session_key, true)
+
+       if err != nil {
+
+               log.Printf("user login: failed to set session: %s", err.Error())
+
+               c.JSON(http.StatusInternalServerError, SERVER_RESP{Status: "error", Reply: "failed to login"})
+
+               return
+
+       }
+
+       c.JSON(http.StatusOK, SERVER_RESP{Status: "success", Reply: "logged in"})
+
+}
diff --git a/pkg/server/api/api_story.go b/pkg/server/api/api_story.go
new file mode 100644 (file)
index 0000000..acdee9d
--- /dev/null
@@ -0,0 +1,281 @@
+package api
+
+import (
+       "encoding/json"
+       "log"
+       "net/http"
+       "strings"
+
+       "github.com/gin-gonic/gin"
+
+       pkgauth "our-wedding-rsvp/pkg/auth"
+       pkgdb "our-wedding-rsvp/pkg/db"
+       pkgutils "our-wedding-rsvp/pkg/utils"
+)
+
+type ArticleInfo struct {
+       Id               string `json:"id,omitempty"`
+       Title            string `json:"title"`
+       Content          string `json:"content,omitempty"`
+       DateMarked       string `json:"dateMarked"`
+       PrimaryMediaName string `json:"primaryMediaName"`
+}
+
+func UploadStory(c *gin.Context) {
+
+       if !pkgauth.Is0(c, nil, nil) {
+
+               log.Printf("article upload: not admin\n")
+
+               c.JSON(http.StatusForbidden, SERVER_RESP{Status: "error", Reply: "you're not admin"})
+
+               return
+
+       }
+
+       var req CLIENT_REQ
+
+       var a_info ArticleInfo
+
+       if err := c.BindJSON(&req); err != nil {
+
+               log.Printf("article upload: failed to bind: %s\n", err.Error())
+
+               c.JSON(http.StatusBadRequest, SERVER_RESP{Status: "error", Reply: "invalid format"})
+
+               return
+       }
+
+       err := json.Unmarshal([]byte(req.Data), &a_info)
+
+       if err != nil {
+
+               log.Printf("article upload: failed to unmarshal: %s\n", err.Error())
+
+               c.JSON(http.StatusBadRequest, SERVER_RESP{Status: "error", Reply: "invalid format"})
+
+               return
+
+       }
+
+       if a_info.Title == "" {
+
+               log.Printf("article upload: needs title\n")
+
+               c.JSON(http.StatusBadRequest, SERVER_RESP{Status: "error", Reply: "invalid format"})
+
+               return
+
+       }
+
+       if a_info.Content == "" {
+
+               log.Printf("article upload: needs content\n")
+
+               c.JSON(http.StatusBadRequest, SERVER_RESP{Status: "error", Reply: "invalid format"})
+
+               return
+
+       }
+
+       if a_info.DateMarked == "" {
+
+               log.Printf("article upload: needs dateMarked\n")
+
+               c.JSON(http.StatusBadRequest, SERVER_RESP{Status: "error", Reply: "invalid format"})
+
+               return
+
+       }
+
+       if a_info.PrimaryMediaName == "" {
+
+               log.Printf("article upload: needs primaryMediaName\n")
+
+               c.JSON(http.StatusBadRequest, SERVER_RESP{Status: "error", Reply: "invalid format"})
+
+               return
+
+       }
+
+       new_file_name, _ := pkgutils.GetRandomHex(32)
+
+       err = pkgdb.SaveStory(new_file_name, a_info.Title, a_info.DateMarked, a_info.PrimaryMediaName, a_info.Content)
+
+       if err != nil {
+
+               log.Printf("article upload: failed to upload: %s", err.Error())
+
+               c.JSON(http.StatusInternalServerError, SERVER_RESP{Status: "error", Reply: "failed to upload"})
+
+               return
+       }
+
+       c.JSON(http.StatusOK, SERVER_RESP{Status: "success", Reply: "uploaded"})
+
+}
+
+func DownloadStoryById(c *gin.Context) {
+
+       watchId := c.Param("storyId")
+
+       if !pkgauth.VerifyDefaultValue(watchId) {
+
+               log.Printf("get article: illegal: %s\n", watchId)
+
+               c.JSON(http.StatusBadRequest, SERVER_RESP{Status: "error", Reply: "invalid format"})
+
+               return
+
+       }
+
+       story, err := pkgdb.GetStoryById(watchId)
+
+       if err != nil {
+
+               log.Printf("failed to get article: %s\n", err.Error())
+
+               c.JSON(http.StatusBadRequest, SERVER_RESP{Status: "error", Reply: "invalid format"})
+
+               return
+       }
+
+       content := story.Content
+
+       c.JSON(http.StatusOK, SERVER_RESP{Status: "success", Reply: content})
+
+}
+
+func UploadStoryMedia(c *gin.Context) {
+
+       if !pkgauth.Is0(c, nil, nil) {
+
+               log.Printf("media upload: not admin\n")
+
+               c.JSON(http.StatusForbidden, SERVER_RESP{Status: "error", Reply: "you're not admin"})
+
+               return
+
+       }
+
+       file, _ := c.FormFile("file")
+
+       rawMediaType := file.Header.Get("Content-Type")
+
+       mediaProplist := strings.Split(rawMediaType, "/")
+
+       //mediaType := mediaProplist[0]
+       mediaExt := mediaProplist[1]
+
+       f_name := file.Filename
+
+       f_name_list := strings.Split(f_name, ".")
+
+       f_name_len := len(f_name_list)
+
+       if f_name_len < 1 {
+
+               log.Println("no extension specified")
+
+               c.JSON(http.StatusBadRequest, SERVER_RESP{Status: "error", Reply: "invalid format"})
+
+               return
+       }
+
+       extension := f_name_list[f_name_len-1]
+
+       log.Printf("received: %s, size: %d, type: %s, ext: %s\n", file.Filename, file.Size, rawMediaType, extension)
+
+       file_name, _ := pkgutils.GetRandomHex(32)
+
+       err := pkgdb.UploadMedia(c, file, file_name)
+
+       if err != nil {
+
+               log.Println(err.Error())
+
+               c.JSON(http.StatusInternalServerError, SERVER_RESP{Status: "error", Reply: "failed to save"})
+
+               return
+
+       }
+
+       client_file_name := file_name + "." + mediaExt
+
+       c.JSON(http.StatusOK, SERVER_RESP{Status: "success", Reply: client_file_name})
+
+}
+
+func DownloadStoryMediaById(c *gin.Context) {
+
+       watchId := c.Param("mediaId")
+
+       if !pkgauth.VerifyMediaKey(watchId) {
+
+               log.Printf("download media: illegal: %s\n", watchId)
+
+               c.JSON(http.StatusBadRequest, SERVER_RESP{Status: "error", Reply: "invalid format"})
+
+               return
+
+       }
+
+       err := pkgdb.DownloadMedia(c, watchId)
+
+       if err != nil {
+
+               log.Printf("download media: %s\n", err.Error())
+
+               c.JSON(http.StatusBadRequest, SERVER_RESP{Status: "error", Reply: "invalid format"})
+
+               return
+
+       }
+
+       log.Println("media download success")
+}
+
+func GetStoryList(c *gin.Context) {
+
+       articles := make([]ArticleInfo, 0)
+
+       stories, err := pkgdb.GetAllStory()
+
+       if err != nil {
+
+               log.Printf("all stories: %s\n", err.Error())
+
+               c.JSON(http.StatusBadRequest, SERVER_RESP{Status: "error", Reply: "invalid format"})
+
+               return
+
+       }
+
+       slen := len(stories)
+
+       for i := 0; i < slen; i++ {
+
+               article := ArticleInfo{
+                       Id:               stories[i].Id,
+                       Title:            stories[i].Title,
+                       DateMarked:       stories[i].DateMarked,
+                       PrimaryMediaName: stories[i].PrimaryMediaName,
+               }
+
+               articles = append(articles, article)
+
+       }
+
+       abytes, err := json.Marshal(articles)
+
+       if err != nil {
+               log.Printf("all stories: marshal: %s\n", err.Error())
+
+               c.JSON(http.StatusBadRequest, SERVER_RESP{Status: "error", Reply: "invalid format"})
+
+               return
+       }
+
+       c.JSON(http.StatusOK, SERVER_RESP{Status: "success", Reply: string(abytes)})
+
+}
index 5a3de858ff938f94adfacc9a82912b5e7d7c43a8..6cf89982aa9da62f9f3e8bc3bdc7f0628d9432cd 100644 (file)
@@ -36,13 +36,29 @@ func configureServer(e *gin.Engine) error {
 
        e.GET("/signin", getSignin)
 
+       e.GET("/signout", Logout)
+
+       e.GET("/story/r/:storyId", getRead)
+
+       e.GET("/story/w", getWrite)
+
+       e.GET("/story/w/:storyId/delete", DeleteStory)
+
        e.GET("/api/oauth2/google/signin", pkgserverapi.OauthGoogleLogin)
 
        e.GET("/oauth2/google/callback", pkgserverapi.OauthGoogleCallback)
 
-       e.GET("/story/r/:storyId", getRead)
+       e.POST("/api/signin", pkgserverapi.Login)
 
-       e.GET("/story/w", getWrite)
+       e.POST("/api/story/upload", pkgserverapi.UploadStory)
+
+       e.POST("/api/story/download/:storyId", pkgserverapi.DownloadStoryById)
+
+       e.POST("/api/media/upload", pkgserverapi.UploadStoryMedia)
+
+       e.GET("/api/media/download/c/:mediaId", pkgserverapi.DownloadStoryMediaById)
+
+       e.GET("/api/story/list", pkgserverapi.GetStoryList)
 
        return nil
 }
index bb9a8392317522710066a9fc6aafe35bc146e6b9..9e6239e570bdc366747a8bca9fbc8d1d9b7a1440 100644 (file)
@@ -1,9 +1,14 @@
 package server
 
 import (
+       "log"
+       "net/http"
+
        "github.com/gin-gonic/gin"
 
        pkgauth "our-wedding-rsvp/pkg/auth"
+       pkgdb "our-wedding-rsvp/pkg/db"
+       pkgserverapi "our-wedding-rsvp/pkg/server/api"
 )
 
 func getIndex(c *gin.Context) {
@@ -27,15 +32,89 @@ func getSignin(c *gin.Context) {
 
 func getRead(c *gin.Context) {
 
-       c.HTML(200, "read.html", gin.H{})
+       watchId := c.Param("storyId")
+
+       if !pkgauth.VerifyDefaultValue(watchId) {
+
+               log.Printf("get article: illegal: %s\n", watchId)
+
+               c.JSON(http.StatusBadRequest, pkgserverapi.SERVER_RESP{Status: "error", Reply: "invalid format"})
+
+               return
+
+       }
+       c.HTML(200, "read.html", gin.H{
+               "article_code": watchId,
+       })
+
 }
 
 func getWrite(c *gin.Context) {
 
-       if !pkgauth.Is0(c) {
+       if !pkgauth.Is0(c, nil, nil) {
                c.HTML(200, "index.html", gin.H{})
                return
        }
 
        c.HTML(200, "write.html", gin.H{})
 }
+
+func Logout(c *gin.Context) {
+
+       userId := ""
+
+       sessionId := ""
+
+       if !pkgauth.Is0(c, &userId, &sessionId) {
+
+               log.Printf("logout: not logged in\n")
+
+               c.JSON(http.StatusBadRequest, pkgserverapi.SERVER_RESP{Status: "error", Reply: "not logged in"})
+
+               return
+
+       }
+
+       err := pkgdb.SetAdminSessionId(userId, sessionId, false)
+
+       if err != nil {
+
+               log.Printf("logout: error: %v\n", err)
+
+               c.JSON(http.StatusBadRequest, pkgserverapi.SERVER_RESP{Status: "error", Reply: "invalid"})
+
+               return
+
+       }
+
+       c.JSON(http.StatusOK, pkgserverapi.SERVER_RESP{Status: "success", Reply: "logged out"})
+
+}
+
+func DeleteStory(c *gin.Context) {
+
+       if !pkgauth.Is0(c, nil, nil) {
+
+               log.Printf("delete: not allowed\n")
+
+               c.JSON(http.StatusBadRequest, pkgserverapi.SERVER_RESP{Status: "error", Reply: "invalid"})
+
+               return
+
+       }
+
+       storyId := c.Param("storyId")
+
+       err := pkgdb.DeleteStoryById(storyId)
+
+       if err != nil {
+               log.Printf("delete: error: %v\n", err)
+
+               c.JSON(http.StatusInternalServerError, pkgserverapi.SERVER_RESP{Status: "error", Reply: "internal error"})
+
+               return
+       }
+
+       c.JSON(http.StatusOK, pkgserverapi.SERVER_RESP{Status: "success", Reply: "deleted"})
+
+}
index 9f3be9143bee13bbae9d16d6cecf8f15523dd3a5..811c0a2070364f42ad41462903e5ae9b410958e7 100644 (file)
@@ -114,7 +114,7 @@ var editor = new EditorJS({
                   success: 1,
                   file: {
 
-                    url: '/api/media/c/' + data.reply,
+                    url: '/api/media/download/c/' + data.reply,
               
                   }
                 }
index cdbb9734b4d0a7c809d3c4befd16277c946ebc49..76e64c089ac077feaeae5a96ba9ffd427c2ab295 100644 (file)
     <script src="https://cdn.jsdelivr.net/npm/@editorjs/inline-code@latest"></script>
     <script src="https://cdn.jsdelivr.net/npm/@editorjs/image@latest"></script>
     <script src="https://cdn.jsdelivr.net/npm/@editorjs/editorjs@latest"></script>
+    <script>
 
+        CONTENT_ID = "{{ .article_code }}"
+  
+    </script>
 
 </head>