Compare commits

...
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

7 Commits
main ... dev

  1. 1
      .dockerignore
  2. 0
      .drone.yml
  3. 14
      Dockerfile
  4. 14
      Makefile
  5. 5
      cmd/admin.go
  6. 22
      cmd/cmd.go
  7. 3
      go.mod
  8. 25
      go.sum
  9. 20
      internal/logger/logger.go
  10. 25
      internal/resource/error.go
  11. 31
      internal/resource/response.go
  12. 35
      internal/response/response.go
  13. 5
      internal/util/write_to_config.go
  14. 3
      main.go
  15. 8
      models/user.go
  16. 11
      modules/authenticate/middleware.go
  17. 23
      modules/cors/cors.go
  18. 17
      services/auth/auth.go
  19. 14
      services/auth/user.go
  20. 10
      services/calendar/calendar.go
  21. 10
      services/services.go
  22. 8
      services/services_min.go
  23. 3
      ui/.browserslistrc
  24. 0
      ui/.env.development
  25. 0
      ui/.env.production
  26. 17
      ui/.eslintrc.js
  27. 23
      ui/.gitignore
  28. 24
      ui/README.md
  29. 5
      ui/babel.config.js
  30. 30
      ui/package.json
  31. BIN
      ui/public/favicon.ico
  32. 17
      ui/public/index.html
  33. 30
      ui/src/App.vue
  34. BIN
      ui/src/assets/logo.png
  35. 59
      ui/src/components/HelloWorld.vue
  36. 13
      ui/src/main.js
  37. 25
      ui/src/router/index.js
  38. 53
      ui/src/theme.sass
  39. 16
      ui/src/views/About.vue
  40. 31
      ui/src/views/Home.vue
  41. 11
      ui/vue.config.js
  42. 8892
      ui/yarn.lock

1
.dockerignore

@ -1,4 +1,5 @@
**/node_modules
**/bin
**/dist
docs
assets

0
ui/.gitkeep → .drone.yml

14
Dockerfile

@ -1,3 +1,14 @@
FROM node as frontend
WORKDIR /src
COPY ./ui/package.json ./ui/yarn.lock /src/
RUN yarn install
COPY ./ui/ .
RUN yarn build
FROM golang:1.15-alpine as backend
RUN apk add --no-cache git gcc musl-dev
@ -10,9 +21,10 @@ COPY go.mod go.sum /src/
RUN go mod download
COPY . .
COPY --from=frontend /src/dist ./ui/dist
RUN go generate
RUN VERSION=$(git describe --tags)-$(git rev-parse --short HEAD) && \
RUN VERSION=$(git describe --tags --abbrev=0)-$(git rev-parse --short HEAD) && \
CGO_ENABLED=1 GOOS=linux \
go build \
-ldflags="-w -X 'github.com/mutsuki333/calendar/cmd.Version=${VERSION}' -X 'github.com/mutsuki333/calendar/services.Version=${VERSION}' -linkmode external -extldflags '-static'" \

14
Makefile

@ -10,8 +10,7 @@ GOPATH := $(GOBASE)/vendor:$(GOBASE)
GOBIN := $(GOBASE)/bin
GOFILES := main.go
LDFLAG=-X 'github.com/mutsuki333/calendar/cmd.Version=$(VERSION)-$(BUILD)'
LDFLAG+=-X 'github.com/mutsuki333/calendar/services.Version=$(VERSION)-$(BUILD)'
LDFLAG=-X 'main.Version=$(VERSION)-$(BUILD)'
LDFLAGS=-ldflags="-w $(LDFLAG)"
# MAKEFLAGS += --silent
@ -40,8 +39,15 @@ min:
go build -tags min $(LDFLAGS) -o $(GOBIN)/$(PROJECTNAME)-min $(GOFILES)
docker-build:
docker build --target backend --cache-from=$(PROJECTNAME):backend -t $(PROJECTNAME):backend .
docker build --target release --cache-from=$(PROJECTNAME):backend -t $(PROJECTNAME) -t $(PROJECTNAME):$(VERSION) .
docker build --target frontend --cache-from=$(PROJECTNAME):frontend -t $(PROJECTNAME):frontend .
docker build --target backend \
--cache-from=$(PROJECTNAME):backend \
--cache-from=$(PROJECTNAME):frontend \
-t $(PROJECTNAME):backend .
docker build --target release \
--cache-from=$(PROJECTNAME):backend \
--cache-from=$(PROJECTNAME):frontend \
-t $(PROJECTNAME) -t $(PROJECTNAME):$(VERSION) .
# -t $(PROJECTNAME):$(VERSION)-$(BUILD) .
docker-run: docker-build

5
cmd/admin.go

@ -1,7 +1,8 @@
package cmd
import (
"github.com/mutsuki333/calendar/internal/logger"
"log"
"github.com/spf13/cobra"
)
@ -9,7 +10,7 @@ var adminCmd = &cobra.Command{
Use: "admin",
Short: "Calendar server admin",
RunE: func(cmd *cobra.Command, args []string) error {
logger.Dbg.Println("Nothing yet")
log.Println("Nothing yet")
return nil
},
}

22
cmd/cmd.go

@ -2,6 +2,8 @@ package cmd
import (
"fmt"
"log"
"os"
"github.com/pkg/browser"
@ -14,14 +16,20 @@ import (
"github.com/robfig/cron/v3"
)
var Version = "development"
var version = "development"
//SetVersionInfo setup version info
func SetVersionInfo(ver string) {
version = ver
RootCmd.Version = ver
}
var RootCmd = &cobra.Command{
Use: "calendar [-flags] [args]",
Short: "A go calendar server",
Long: `
Starts the calendar server`,
Version: Version,
Version: version,
RunE: start,
}
@ -42,6 +50,15 @@ func init() {
RootCmd.PersistentFlags().Bool("save", false, "Save config for future usage.")
RootCmd.PersistentFlags().StringP("yaml", "y", viper.GetString("data"), "Location of config file to read from.")
file, err := os.OpenFile("info.log", os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
log.Fatal(err)
}
defer file.Close()
log.SetOutput(file)
log.Print("Server started!")
}
func start(cmd *cobra.Command, args []string) error {
@ -57,6 +74,7 @@ func start(cmd *cobra.Command, args []string) error {
c := cron.New()
c.AddFunc("30 * * * *", func() { fmt.Println("Every half hour") })
c.Start()
services.SetVersionInfo(version)
services.Start()
return nil
}

3
go.mod

@ -5,9 +5,7 @@ go 1.15
require (
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751
github.com/gin-gonic/gin v1.6.3
github.com/go-openapi/swag v0.19.11 // indirect
github.com/go-playground/validator/v10 v10.4.1 // indirect
github.com/gofrs/uuid v3.3.0+incompatible // indirect
github.com/golang/protobuf v1.4.3 // indirect
github.com/google/uuid v1.1.2
github.com/json-iterator/go v1.1.10 // indirect
@ -24,7 +22,6 @@ require (
github.com/ugorji/go v1.1.13 // indirect
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897
golang.org/x/sys v0.0.0-20201020230747-6e5568b54d1a // indirect
golang.org/x/text v0.3.4 // indirect
google.golang.org/protobuf v1.25.0 // indirect
gorm.io/driver/sqlite v1.1.3
gorm.io/gorm v1.20.4

25
go.sum

@ -78,10 +78,6 @@ github.com/go-openapi/jsonreference v0.19.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3Hfo
github.com/go-openapi/jsonreference v0.19.4 h1:3Vw+rh13uq2JFNxgnMTGE1rnoieU9FmyE1gvnyylsYg=
github.com/go-openapi/jsonreference v0.19.4/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
github.com/go-openapi/spec v0.19.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
github.com/go-openapi/spec v0.19.9 h1:9z9cbFuZJ7AcvOHKIY+f6Aevb4vObNDkTEyoMfO7rAc=
github.com/go-openapi/spec v0.19.9/go.mod h1:vqK/dIdLGCosfvYsQV3WfC7N3TiZSnGY2RZKoFK7X28=
github.com/go-openapi/spec v0.19.11 h1:ogU5q8dtp3MMPn59a9VRrPKVxvJHEs5P7yNMR5sNnis=
github.com/go-openapi/spec v0.19.11/go.mod h1:vqK/dIdLGCosfvYsQV3WfC7N3TiZSnGY2RZKoFK7X28=
github.com/go-openapi/spec v0.19.14 h1:r4fbYFo6N4ZelmSX8G6p+cv/hZRXzcuqQIADGT1iNKM=
github.com/go-openapi/spec v0.19.14/go.mod h1:gwrgJS15eCUgjLpMjBJmbZezCsw88LmgeEip0M63doA=
github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
@ -100,9 +96,6 @@ github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GO
github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE=
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gobuffalo/here v0.6.0 h1:hYrd0a6gDmWxBM4TnrGw8mQg24iSVoIkHEk7FodQcBI=
github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM=
github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
@ -205,8 +198,6 @@ github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e h1:hB2xlXdHp/pmPZq
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/markbates/pkger v0.17.1 h1:/MKEtWqtc0mZvu9OinB9UzVN9iYCwLWuyUv4Bw+PCno=
github.com/markbates/pkger v0.17.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
@ -304,8 +295,6 @@ github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14/go.mod h1:gxQT6pBGRuI
github.com/swaggo/gin-swagger v1.2.0 h1:YskZXEiv51fjOMTsXrOetAjrMDfFaXD79PEoQBOe2W0=
github.com/swaggo/gin-swagger v1.2.0/go.mod h1:qlH2+W7zXGZkczuL+r2nEBR2JTT+/lX05Nn6vPhc7OI=
github.com/swaggo/swag v1.5.1/go.mod h1:1Bl9F/ZBpVWh22nY0zmYyASPO1lI/zIwRDrpZU+tv8Y=
github.com/swaggo/swag v1.6.9 h1:BukKRwZjnEcUxQt7Xgfrt9fpav0hiWw9YimdNO9wssw=
github.com/swaggo/swag v1.6.9/go.mod h1:a0IpNeMfGidNOcm2TsqODUh9JHdHu3kxDA0UlGbBKjI=
github.com/swaggo/swag v1.7.0 h1:5bCA/MTLQoIqDXXyHfOpMeDvL9j68OY/udlK4pQoo4E=
github.com/swaggo/swag v1.7.0/go.mod h1:BdPIL73gvS9NBsdi7M1JOxLvlbfvNRaBP8m6WT6Aajo=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
@ -323,12 +312,9 @@ github.com/ugorji/go/codec v1.1.13 h1:013LbFhocBoIqgHeIHKlV4JWYhqogATYWZhIcH0WHn
github.com/ugorji/go/codec v1.1.13/go.mod h1:oNVt3Dq+FO91WNQ/9JnHKQP2QJxTzoN7wCBFCq1OeuU=
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli/v2 v2.2.0 h1:JTTnM6wKzdA0Jqodd966MVj4vWbbquZykeX1sKbe2C4=
github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M=
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
@ -383,11 +369,7 @@ golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR
golang.org/x/net v0.0.0-20190611141213-3f473d35a33a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201027133719-8eef5233e2a1 h1:IEhJ99VWSYpHIxjlbu3DQyHegGPnQYAv0IaCX9KHyG0=
golang.org/x/net v0.0.0-20201027133719-8eef5233e2a1/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@ -398,7 +380,6 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -419,7 +400,6 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0 h1:HyfiK1WMnHj5FXFXatD+Qs1A/
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201020230747-6e5568b54d1a h1:e3IU37lwO4aq3uoRKINC7JikojFmE5gO7xhfxs8VC34=
golang.org/x/sys v0.0.0-20201020230747-6e5568b54d1a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -454,10 +434,6 @@ golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200820010801-b793a1359eac h1:DugppSxw0LSF8lcjaODPJZoDzq0ElTGskTst3ZaBkHI=
golang.org/x/tools v0.0.0-20200820010801-b793a1359eac/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20201028141808-0dcbe3655aa6 h1:rA8dKoUwU9oduWs6/HC4BhGwJ5jnNpAv3AWekvp+QM4=
golang.org/x/tools v0.0.0-20201028141808-0dcbe3655aa6/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201120155355-20be4ac4bd6e h1:t96dS3DO8DGjawSLJL/HIdz8CycAd2v07XxqB3UPTi0=
golang.org/x/tools v0.0.0-20201120155355-20be4ac4bd6e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -516,7 +492,6 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=

20
internal/logger/logger.go

@ -1,20 +0,0 @@
package logger
import (
"log"
"os"
)
var (
Dbg *log.Logger
Inf *log.Logger
Wrn *log.Logger
Err *log.Logger
)
func init() {
Dbg = log.New(os.Stdout, "DEBUG: ", log.Ldate|log.Ltime|log.Lshortfile)
Inf = log.New(os.Stdout, "INFO: ", log.Ldate|log.Ltime)
Wrn = log.New(os.Stdout, "WARN: ", log.Ldate|log.Ltime|log.Lshortfile)
Err = log.New(os.Stderr, "ERROR: ", log.Ldate|log.Ltime|log.Lshortfile)
}

25
internal/resource/error.go

@ -1,25 +0,0 @@
package resource
import (
"net/http"
"github.com/gin-gonic/gin"
)
type RequestError struct {
Message string `json:"message" example:"status bad request"`
}
type BaseError struct {
Code int `json:"code" example:"400"`
Message string `json:"message" example:"status bad request"`
}
//NotFound Response err with 400
func Abort(ctx *gin.Context, err error) {
er := BaseError{
Code: http.StatusBadRequest,
Message: err.Error(),
}
ctx.AbortWithStatusJSON(http.StatusBadRequest, er)
}

31
internal/resource/response.go

@ -1,31 +0,0 @@
package resource
import (
"net/http"
"github.com/gin-gonic/gin"
)
//BaseResponse base response structure
type BaseResponse struct {
Code int `json:"code" example:"200"`
Message string `json:"message" example:"ok"`
}
//MakeResponse returns 200 with simple *msg*
func MakeResponse(ctx *gin.Context, msg string) {
res := BaseResponse{
Code: http.StatusOK,
Message: msg,
}
ctx.JSON(http.StatusOK, res)
}
//Ok returns 200 with message:"ok"
func Ok(ctx *gin.Context) {
res := BaseResponse{
Code: http.StatusOK,
Message: "ok",
}
ctx.JSON(http.StatusOK, res)
}

35
internal/response/response.go

@ -0,0 +1,35 @@
package response
import (
"net/http"
"github.com/gin-gonic/gin"
)
//MakeResponse returns 200 with simple *msg*
func MakeResponse(ctx *gin.Context, msg string) {
ctx.JSON(http.StatusOK, gin.H{
"message": msg,
})
}
//Ok returns 200 with message:"ok"
func Ok(ctx *gin.Context) {
ctx.JSON(http.StatusOK, gin.H{
"message": "ok",
})
}
//AbortError abort with error
func AbortError(ctx *gin.Context, err error) {
ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
"message": err.Error(),
})
}
//Abort abort with error
func Abort(ctx *gin.Context, code int, msg string) {
ctx.AbortWithStatusJSON(code, gin.H{
"message": msg,
})
}

5
internal/util/write_to_config.go

@ -1,11 +1,10 @@
package util
import (
"log"
"os"
"path/filepath"
"github.com/mutsuki333/calendar/internal/logger"
"github.com/spf13/viper"
)
@ -25,7 +24,7 @@ func ReadConfig(path string) {
//WriteConfig Writes config at *path*
func WriteConfig(path string) {
viper.WriteConfigAs(getConfigFile(path))
logger.Inf.Println("Config saved.")
log.Println("Config saved.")
}
func getConfigFile(path string) string {

3
main.go

@ -4,8 +4,11 @@ import (
"github.com/mutsuki333/calendar/cmd"
)
var Version = "development"
//go:generate statik -src=ui/dist -dest=assets -f
//go:generate swag init -g services/services.go
func main() {
cmd.SetVersionInfo(Version)
cmd.RootCmd.Execute()
}

8
models/user.go

@ -2,10 +2,10 @@ package models
import (
"errors"
"log"
"strings"
"github.com/mutsuki333/calendar/internal/constants"
"github.com/mutsuki333/calendar/internal/logger"
"golang.org/x/crypto/bcrypt"
"gorm.io/gorm"
@ -27,7 +27,7 @@ func (usr *User) ChangePassword(to string) (err error) {
return err
}
if err := db.Model(&usr).Update("password", string(bytes)).Error; err != nil {
logger.Dbg.Println(err)
log.Println(err)
}
return err
}
@ -42,7 +42,7 @@ func (usr *User) ValidatePassword(pwd string) error {
func InsertUser(name, email, password string) error {
bytes, err := bcrypt.GenerateFromPassword([]byte(password), 14)
if err != nil {
logger.Err.Println(err)
log.Println(err)
return err
}
user := &User{
@ -52,7 +52,7 @@ func InsertUser(name, email, password string) error {
Level: constants.User,
}
if err := db.Create(&user).Error; err != nil {
logger.Err.Println(err)
log.Println(err)
return errors.New("creating error")
}
return nil

11
modules/authenticate/middleware.go

@ -3,6 +3,7 @@ package authenticate
import (
"crypto/sha1"
"fmt"
"net/http"
"time"
"github.com/gin-gonic/gin"
@ -63,7 +64,15 @@ func LoginUser(c *gin.Context, userID uint) {
if err := db.Create(&session).Error; err != nil {
return
}
c.SetCookie(cookieName, session.SessionID, 60*30, "/", c.Request.Host, shouldSecure, true)
http.SetCookie(c.Writer, &http.Cookie{
Name: cookieName,
MaxAge: 60 * 30,
Value: session.SessionID,
SameSite: http.SameSiteNoneMode,
Secure: shouldSecure,
Path: "/",
})
// c.SetCookie(cookieName, session.SessionID, 60*30, "/", c.Request.Host, true, true)
}
func LogoutUser(c *gin.Context) {

23
modules/cors/cors.go

@ -0,0 +1,23 @@
package cors
import (
"github.com/gin-gonic/gin"
)
//CORSMiddleware add cors to api
func CORSMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
c.Writer.Header().Set("Access-Control-Allow-Origin", "http://localhost:8080")
c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
// c.Writer.Header().Set("Access-Control-Allow-Headers", "*")
c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With")
c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT, PATCH, DELETE")
if c.Request.Method == "OPTIONS" {
c.AbortWithStatus(204)
return
}
c.Next()
}
}

17
services/auth/auth.go

@ -5,7 +5,7 @@ import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/mutsuki333/calendar/internal/resource"
"github.com/mutsuki333/calendar/internal/response"
"github.com/mutsuki333/calendar/models"
"github.com/mutsuki333/calendar/modules/authenticate"
)
@ -13,9 +13,10 @@ import (
//RegisterAuthService registers auth service to api
func RegisterAuthService(api *gin.RouterGroup) {
auth := api.Group("/auth")
auth.GET("/", getAuthStatus)
auth.GET("", getAuthStatus)
auth.POST("/login", login)
auth.POST("/logout", logout)
auth.POST("/token", token)
}
// @Summary Get Auth Status
@ -51,25 +52,25 @@ type loginRequest struct {
func login(c *gin.Context) {
var param loginRequest
if err := c.ShouldBindJSON(&param); err != nil {
resource.Abort(c, err)
response.AbortError(c, err)
return
}
user, err := models.GetUser(param.Username)
if err != nil {
resource.Abort(c, err)
response.AbortError(c, err)
return
}
pwd, err := base64.URLEncoding.DecodeString(param.PwdB64)
if err != nil {
resource.Abort(c, err)
response.AbortError(c, err)
return
}
if err := user.ValidatePassword(string(pwd)); err != nil {
resource.Abort(c, err)
response.AbortError(c, err)
return
}
authenticate.LoginUser(c, user.ID)
resource.Ok(c)
response.Ok(c)
}
@ -81,7 +82,7 @@ func login(c *gin.Context) {
// @Router /auth/logout [post]
func logout(c *gin.Context) {
authenticate.LogoutUser(c)
resource.Ok(c)
response.Ok(c)
}
// @Summary Get Token

14
services/auth/user.go

@ -3,20 +3,20 @@ package auth
import (
"encoding/base64"
"fmt"
"log"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"github.com/mutsuki333/calendar/internal/logger"
"github.com/mutsuki333/calendar/internal/resource"
"github.com/mutsuki333/calendar/internal/response"
"github.com/mutsuki333/calendar/models"
)
//RegisterUserService registers user services
func RegisterUserService(api *gin.RouterGroup) {
user := api.Group("/user")
user.POST("/", postUser)
user.GET("/", listUsers)
user.POST("", postUser)
user.GET("", listUsers)
user.GET("/:id", getUser)
user.PUT("/:id", updateUser)
user.DELETE("/:id", deleteUser)
@ -46,7 +46,7 @@ func postUser(c *gin.Context) {
return
}
logger.Dbg.Println(data)
log.Println(data)
pwd, err := base64.URLEncoding.DecodeString(data.PwdB64)
if err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
@ -88,12 +88,12 @@ func listUsers(c *gin.Context) {
func getUser(c *gin.Context) {
userID, err := strconv.Atoi(c.Param("id"))
if err != nil {
resource.Abort(c, err)
response.AbortError(c, err)
return
}
user, err := models.LoadUser(uint(userID))
if err != nil {
resource.Abort(c, err)
response.AbortError(c, err)
return
}
c.JSON(200, user)

10
services/calendar/calendar.go

@ -1,23 +1,23 @@
package calendar
import (
"log"
"net/http"
"github.com/gin-gonic/gin"
"github.com/mutsuki333/calendar/internal/logger"
"github.com/mutsuki333/calendar/models"
)
func RegisterCalendarService(api *gin.RouterGroup) {
route := api.Group("/calendar")
route.GET("/", listCalendars)
route.POST("/", postCalendar)
route.GET("", listCalendars)
route.POST("", postCalendar)
route.GET("/:calendarID", getCalendar)
route.PUT("/:calendarID", putCalendar)
route.DELETE("/:calendarID", deleteCalendar)
ics := api.Group("/ics")
ics.POST("/", importCalendarICS)
ics.POST("", importCalendarICS)
ics.GET("/:calendarID", getCalendarICS)
}
@ -42,7 +42,7 @@ func listCalendars(c *gin.Context) {
// @Router /calendar/{calendarID} [get]
func getCalendar(c *gin.Context) {
calendarID := c.Param("calendarID")
logger.Dbg.Println(calendarID)
log.Println(calendarID)
c.JSON(200, gin.H{
"message": "update user",
})

10
services/services.go

@ -17,8 +17,12 @@ import (
ginSwagger "github.com/swaggo/gin-swagger"
)
//Version shows the version of the build.
var Version = "development"
var version = "development"
//SetVersionInfo setup version info
func SetVersionInfo(ver string) {
version = ver
}
//Start starts the service server.
// @title Calendar API
@ -56,7 +60,7 @@ func Start() {
if viper.GetBool("swagger.enabled") {
docs.SwaggerInfo.Host = ""
docs.SwaggerInfo.BasePath = "/api"
docs.SwaggerInfo.Version = Version
docs.SwaggerInfo.Version = version
server.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
}

8
services/services_min.go

@ -12,8 +12,12 @@ import (
"github.com/spf13/viper"
)
//Version shows the version of the build.
var Version = "development"
var version = "development"
//SetVersionInfo setup version info
func SetVersionInfo(ver string) {
version = ver
}
//Start starts the service server.
func Start() {

3
ui/.browserslistrc

@ -0,0 +1,3 @@
> 1%
last 2 versions
not dead

0
ui/.env.development

0
ui/.env.production

17
ui/.eslintrc.js

@ -0,0 +1,17 @@
module.exports = {
root: true,
env: {
node: true
},
'extends': [
'plugin:vue/vue3-essential',
'eslint:recommended'
],
parserOptions: {
parser: 'babel-eslint'
},
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off'
}
}

23
ui/.gitignore

@ -0,0 +1,23 @@
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

24
ui/README.md

@ -0,0 +1,24 @@
# ui
## Project setup
```
yarn install
```
### Compiles and hot-reloads for development
```
yarn serve
```
### Compiles and minifies for production
```
yarn build
```
### Lints and fixes files
```
yarn lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).

5
ui/babel.config.js

@ -0,0 +1,5 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}

30
ui/package.json

@ -0,0 +1,30 @@
{
"name": "ui",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"axios": "^0.21.1",
"bulma": "^0.9.1",
"core-js": "^3.6.5",
"vue": "^3.0.0",
"vue-router": "^4.0.0-0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-plugin-router": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"@vue/compiler-sfc": "^3.0.0",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^7.0.0-0",
"sass": "^1.26.5",
"sass-loader": "^8.0.2",
"vue-cli-plugin-pug": "~2.0.0"
}
}

BIN
ui/public/favicon.ico

17
ui/public/index.html

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

30
ui/src/App.vue

@ -0,0 +1,30 @@
<template>
<div id="nav">
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</div>
<router-view/>
</template>
<style lang="scss">
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
#nav {
padding: 30px;
a {
font-weight: bold;
color: #2c3e50;
&.router-link-exact-active {
color: #42b983;
}
}
}
</style>

BIN
ui/src/assets/logo.png

After

Width: 200  |  Height: 200  |  Size: 6.7 KiB

59
ui/src/components/HelloWorld.vue

@ -0,0 +1,59 @@
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For a guide and recipes on how to configure / customize this project,<br>
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
</p>
<h3>Installed CLI Plugins</h3>
<ul>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-router" target="_blank" rel="noopener">router</a></li>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
</ul>
<h3>Essential Links</h3>
<ul>
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
</ul>
<h3>Ecosystem</h3>
<ul>
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
</ul>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>

13
ui/src/main.js

@ -0,0 +1,13 @@
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import axios from 'axios'
import '@/theme.sass'
axios.defaults.baseURL = '/api/'
axios.defaults.withCredentials = true
axios.defaults.debug = true
const app = createApp(App)
app.config.globalProperties.$http = axios
app.use(router).mount('#app')

25
ui/src/router/index.js

@ -0,0 +1,25 @@
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
}
]
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
})
export default router

53
ui/src/theme.sass

@ -0,0 +1,53 @@
@charset "utf-8"
@import "../node_modules/bulma/bulma.sass"
.big-title
font-size: 50px
.circle
width: 1rem
height: 1rem
border-radius: 50%
border: 1px black solid
display: inline-block
.red
color: red
.img
width: 100%
height: auto
.hover
cursor: pointer
display: inline-block
vertical-align: middle
-webkit-transform: perspective(1px) translateZ(0)
transform: perspective(1px) translateZ(0)
box-shadow: 0 0 1px rgba(0, 0, 0, 0)
-webkit-transition-duration: 0.3s
transition-duration: 0.3s
-webkit-transition-property: box-shadow, transform
transition-property: box-shadow, transform
.hover:hover, .hover:focus, .hover:active
box-shadow: 0 10px 10px -10px rgba(0, 0, 0, 0.5)
-webkit-transform: scale(1.1)
transform: scale(1.1)
.shrink
cursor: pointer
display: inline-block
vertical-align: middle
-webkit-transform: perspective(1px) translateZ(0)
transform: perspective(1px) translateZ(0)
box-shadow: 0 0 1px rgba(0, 0, 0, 0)
-webkit-transition-duration: 0.3s
transition-duration: 0.3
-webkit-transition-property: transform
transition-property: transform
.shrink:hover, .shrink:focus, .shrink:active
-webkit-transform: scale(0.9)
transform: scale(0.9)

16
ui/src/views/About.vue

@ -0,0 +1,16 @@
<template lang="pug">
.about
h1 this is about page
</template>
<script>
export default {
created () {
this.$http.post("auth/login",{
"password": "YWRtaW4=",
"username": "admin"
})
.then(res=>console.log(res.data.message))
}
}
</script>

31
ui/src/views/Home.vue

@ -0,0 +1,31 @@
<template lang="pug">
.home
h1.test Home
p {{content}}
</template>
<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'
export default {
name: 'Home',
components: {
HelloWorld
},
data () {
return {
content: ''
}
},
created () {
this.$http.get("auth")
.then(res=>console.log(res))
}
}
</script>
<style lang="sass" scoped>
.test
color: red
</style>

11
ui/vue.config.js

@ -0,0 +1,11 @@
module.exports = {
devServer: {
proxy:{
'^/api':{
target: 'http://localhost:5000',
ws: false,
changeOrigin: true
}
}
}
}

8892
ui/yarn.lock
File diff suppressed because it is too large
View File