From ddde7b198136a0c19101fbb4441adb6991b366c9 Mon Sep 17 00:00:00 2001 From: linshengqian Date: Sun, 31 Mar 2024 22:26:11 +0800 Subject: [PATCH] gin-gorm-oj --- .idea/.gitignore | 8 + .idea/gin-gorm-oj.iml | 9 + .idea/go.imports.xml | 7 + .idea/modules.xml | 8 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + code/code_user/main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + .../main.go | 10 + code/runner.go | 28 + define/define.go | 6 + docs/docs.go | 653 ++++++++++++++++++ docs/swagger.json | 624 +++++++++++++++++ docs/swagger.yaml | 408 +++++++++++ gin-gorm-oj | 1 + go.mod | 59 ++ go.sum | 175 +++++ helper/helper.go | 115 +++ main.go | 9 + middlewares/auth_admin.go | 32 + middlewares/auth_user.go | 35 + models/category_basic.go | 16 + models/init.go | 28 + models/problem_basic.go | 33 + models/problem_category.go | 16 + models/submit_basic.go | 35 + models/test_case.go | 15 + models/user_basic.go | 21 + router/app.go | 56 ++ service/category.go | 170 +++++ service/problem.go | 310 +++++++++ service/submit.go | 239 +++++++ service/user.go | 255 +++++++ test/email_test.go | 26 + test/gorm_test.go | 25 + test/jwt_test.go | 54 ++ test/redis_test.go | 37 + test/uuid_test.go | 16 + 89 files changed, 4089 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/gin-gorm-oj.iml create mode 100644 .idea/go.imports.xml create mode 100644 .idea/modules.xml create mode 100644 code/00c0541c-ee12-47a7-9d0f-cf0c5a39e09c/main.go create mode 100644 code/09bb8c34-a627-4231-86f1-73ebbd9b1582/main.go create mode 100644 code/0ddbdc45-1cc1-4b1b-ab0e-d43b6ec2bc24/main.go create mode 100644 code/10e34d06-b2e3-43f9-b993-605ea662a777/main.go create mode 100644 code/1428deb5-fc2e-4a1c-b16f-32d86109b9cf/main.go create mode 100644 code/1cb7600e-ab76-4369-99a6-4ca30753ccb4/main.go create mode 100644 code/20919172-2e92-47a9-b4b1-bbce938d0e91/main.go create mode 100644 code/286517ab-d294-4b56-b437-044e8e53669f/main.go create mode 100644 code/34ac8555-b79c-4fc3-b888-64b1039b8893/main.go create mode 100644 code/35b30b49-aa22-40c8-b1d8-8a01d4aa8d2e/main.go create mode 100644 code/3a14b01b-a415-45b2-9f9c-c6a64b2b3019/main.go create mode 100644 code/3c4b47df-7dfe-4155-911a-06128d00a5f3/main.go create mode 100644 code/3df4aaa4-2b11-415e-a267-988cf45178e1/main.go create mode 100644 code/3e949edd-caa8-4159-b746-fd8b3c72d963/main.go create mode 100644 code/3fc12ddd-f29d-4070-a663-71b3d98da997/main.go create mode 100644 code/436e15e1-def4-4374-9c2c-a6fd7f6c2f18/main.go create mode 100644 code/4c9a0075-4467-4869-a8c2-6f7991a71c12/main.go create mode 100644 code/51763dc6-c29b-4988-ba0c-b50538f0182f/main.go create mode 100644 code/52b02072-e991-4e8d-8070-38f6b75c75a6/main.go create mode 100644 code/611590a5-7457-4d35-b6b6-f63180d833a8/main.go create mode 100644 code/66ab7e0b-50d1-4757-9eeb-94a711f75a56/main.go create mode 100644 code/6a9f83b9-f907-4586-a455-1fa50651db17/main.go create mode 100644 code/6e832308-ba23-41f7-9e48-0cc478dbbf04/main.go create mode 100644 code/7025963e-8e4a-4a93-90c7-d59d8494ea38/main.go create mode 100644 code/73e8bd21-dcca-483a-8224-a023028c6891/main.go create mode 100644 code/748ba15f-e625-480a-aed9-5c80ccbc2417/main.go create mode 100644 code/74f14be1-1d7f-4eb6-8bb7-66e0c16422f6/main.go create mode 100644 code/79f3a2da-5197-438e-9948-4f3fa05a21f5/main.go create mode 100644 code/7b1eb8ac-8fa1-4976-823b-22cd3059e4b8/main.go create mode 100644 code/80089deb-ff4c-4b5f-88b7-18973e49e16e/main.go create mode 100644 code/87ad3870-15c5-4920-8f78-517ef85c43a7/main.go create mode 100644 code/88c851a8-9add-4f1a-a38e-59ef9d0abf4e/main.go create mode 100644 code/8ff8ecf3-62bf-4fb4-90f3-2ff10916c9d4/main.go create mode 100644 code/95476d8f-99ad-4f8a-8564-aeb2847ca6bb/main.go create mode 100644 code/999030bf-8eb6-4178-adbb-256fab98e796/main.go create mode 100644 code/9c7af05b-6a03-4a0a-aeb8-353ea000c435/main.go create mode 100644 code/9cc60fcb-4401-4bbf-99d2-1337d5133e76/main.go create mode 100644 code/9e0330fc-c22c-41d8-a197-d476d2f87e84/main.go create mode 100644 code/9e495e85-0992-4987-b32c-cfdbe8cee8ba/main.go create mode 100644 code/a23ba488-f9cc-46de-923a-d113fc5b3f40/main.go create mode 100644 code/a381c90d-fc6a-42d8-8e2f-7a502ff2f769/main.go create mode 100644 code/a4a4564b-8599-424c-80da-83c5343d79ea/main.go create mode 100644 code/ad3d4eb0-7afc-4b70-aa00-991e3da5be2b/main.go create mode 100644 code/ad9538b6-0659-4b7a-96c2-3845c6b92fbe/main.go create mode 100644 code/c03c47f7-4069-479a-9fe2-f915473c6997/main.go create mode 100644 code/c7557548-e675-493d-94c4-73248303a918/main.go create mode 100644 code/ca660014-e21a-41b0-b5ac-26ccb88a9c10/main.go create mode 100644 code/cd4a099d-4f0d-45bc-9028-c601f3de68be/main.go create mode 100644 code/code_user/main.go create mode 100644 code/d7705570-39c9-4776-9ac0-6ff0b24e65a2/main.go create mode 100644 code/daa08bd4-135f-4dca-a152-6aeb90afa938/main.go create mode 100644 code/db7be0f4-17c2-4aa1-80a9-d45c9bf86da5/main.go create mode 100644 code/dcd15341-a8d5-4da8-9bfc-0455bc393231/main.go create mode 100644 code/e2c24aed-8673-47ea-a93e-f968c88a6efc/main.go create mode 100644 code/f8b6272d-d7cf-4d03-b06b-e9a125a8f549/main.go create mode 100644 code/fc328f1d-3859-4a8b-b8e5-572521e4fdfb/main.go create mode 100644 code/runner.go create mode 100644 define/define.go create mode 100644 docs/docs.go create mode 100644 docs/swagger.json create mode 100644 docs/swagger.yaml create mode 160000 gin-gorm-oj create mode 100644 go.mod create mode 100644 go.sum create mode 100644 helper/helper.go create mode 100644 main.go create mode 100644 middlewares/auth_admin.go create mode 100644 middlewares/auth_user.go create mode 100644 models/category_basic.go create mode 100644 models/init.go create mode 100644 models/problem_basic.go create mode 100644 models/problem_category.go create mode 100644 models/submit_basic.go create mode 100644 models/test_case.go create mode 100644 models/user_basic.go create mode 100644 router/app.go create mode 100644 service/category.go create mode 100644 service/problem.go create mode 100644 service/submit.go create mode 100644 service/user.go create mode 100644 test/email_test.go create mode 100644 test/gorm_test.go create mode 100644 test/jwt_test.go create mode 100644 test/redis_test.go create mode 100644 test/uuid_test.go diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..35410ca --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml +# 基于编辑器的 HTTP 客户端请求 +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/gin-gorm-oj.iml b/.idea/gin-gorm-oj.iml new file mode 100644 index 0000000..5e764c4 --- /dev/null +++ b/.idea/gin-gorm-oj.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/go.imports.xml b/.idea/go.imports.xml new file mode 100644 index 0000000..7313580 --- /dev/null +++ b/.idea/go.imports.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..7d71151 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/code/00c0541c-ee12-47a7-9d0f-cf0c5a39e09c/main.go b/code/00c0541c-ee12-47a7-9d0f-cf0c5a39e09c/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/00c0541c-ee12-47a7-9d0f-cf0c5a39e09c/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/09bb8c34-a627-4231-86f1-73ebbd9b1582/main.go b/code/09bb8c34-a627-4231-86f1-73ebbd9b1582/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/09bb8c34-a627-4231-86f1-73ebbd9b1582/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/0ddbdc45-1cc1-4b1b-ab0e-d43b6ec2bc24/main.go b/code/0ddbdc45-1cc1-4b1b-ab0e-d43b6ec2bc24/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/0ddbdc45-1cc1-4b1b-ab0e-d43b6ec2bc24/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/10e34d06-b2e3-43f9-b993-605ea662a777/main.go b/code/10e34d06-b2e3-43f9-b993-605ea662a777/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/10e34d06-b2e3-43f9-b993-605ea662a777/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/1428deb5-fc2e-4a1c-b16f-32d86109b9cf/main.go b/code/1428deb5-fc2e-4a1c-b16f-32d86109b9cf/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/1428deb5-fc2e-4a1c-b16f-32d86109b9cf/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/1cb7600e-ab76-4369-99a6-4ca30753ccb4/main.go b/code/1cb7600e-ab76-4369-99a6-4ca30753ccb4/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/1cb7600e-ab76-4369-99a6-4ca30753ccb4/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/20919172-2e92-47a9-b4b1-bbce938d0e91/main.go b/code/20919172-2e92-47a9-b4b1-bbce938d0e91/main.go new file mode 100644 index 0000000..ab8eee4 --- /dev/null +++ b/code/20919172-2e92-47a9-b4b1-bbce938d0e91/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b+1) +} diff --git a/code/286517ab-d294-4b56-b437-044e8e53669f/main.go b/code/286517ab-d294-4b56-b437-044e8e53669f/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/286517ab-d294-4b56-b437-044e8e53669f/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/34ac8555-b79c-4fc3-b888-64b1039b8893/main.go b/code/34ac8555-b79c-4fc3-b888-64b1039b8893/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/34ac8555-b79c-4fc3-b888-64b1039b8893/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/35b30b49-aa22-40c8-b1d8-8a01d4aa8d2e/main.go b/code/35b30b49-aa22-40c8-b1d8-8a01d4aa8d2e/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/35b30b49-aa22-40c8-b1d8-8a01d4aa8d2e/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/3a14b01b-a415-45b2-9f9c-c6a64b2b3019/main.go b/code/3a14b01b-a415-45b2-9f9c-c6a64b2b3019/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/3a14b01b-a415-45b2-9f9c-c6a64b2b3019/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/3c4b47df-7dfe-4155-911a-06128d00a5f3/main.go b/code/3c4b47df-7dfe-4155-911a-06128d00a5f3/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/3c4b47df-7dfe-4155-911a-06128d00a5f3/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/3df4aaa4-2b11-415e-a267-988cf45178e1/main.go b/code/3df4aaa4-2b11-415e-a267-988cf45178e1/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/3df4aaa4-2b11-415e-a267-988cf45178e1/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/3e949edd-caa8-4159-b746-fd8b3c72d963/main.go b/code/3e949edd-caa8-4159-b746-fd8b3c72d963/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/3e949edd-caa8-4159-b746-fd8b3c72d963/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/3fc12ddd-f29d-4070-a663-71b3d98da997/main.go b/code/3fc12ddd-f29d-4070-a663-71b3d98da997/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/3fc12ddd-f29d-4070-a663-71b3d98da997/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/436e15e1-def4-4374-9c2c-a6fd7f6c2f18/main.go b/code/436e15e1-def4-4374-9c2c-a6fd7f6c2f18/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/436e15e1-def4-4374-9c2c-a6fd7f6c2f18/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/4c9a0075-4467-4869-a8c2-6f7991a71c12/main.go b/code/4c9a0075-4467-4869-a8c2-6f7991a71c12/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/4c9a0075-4467-4869-a8c2-6f7991a71c12/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/51763dc6-c29b-4988-ba0c-b50538f0182f/main.go b/code/51763dc6-c29b-4988-ba0c-b50538f0182f/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/51763dc6-c29b-4988-ba0c-b50538f0182f/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/52b02072-e991-4e8d-8070-38f6b75c75a6/main.go b/code/52b02072-e991-4e8d-8070-38f6b75c75a6/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/52b02072-e991-4e8d-8070-38f6b75c75a6/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/611590a5-7457-4d35-b6b6-f63180d833a8/main.go b/code/611590a5-7457-4d35-b6b6-f63180d833a8/main.go new file mode 100644 index 0000000..ab8eee4 --- /dev/null +++ b/code/611590a5-7457-4d35-b6b6-f63180d833a8/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b+1) +} diff --git a/code/66ab7e0b-50d1-4757-9eeb-94a711f75a56/main.go b/code/66ab7e0b-50d1-4757-9eeb-94a711f75a56/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/66ab7e0b-50d1-4757-9eeb-94a711f75a56/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/6a9f83b9-f907-4586-a455-1fa50651db17/main.go b/code/6a9f83b9-f907-4586-a455-1fa50651db17/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/6a9f83b9-f907-4586-a455-1fa50651db17/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/6e832308-ba23-41f7-9e48-0cc478dbbf04/main.go b/code/6e832308-ba23-41f7-9e48-0cc478dbbf04/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/6e832308-ba23-41f7-9e48-0cc478dbbf04/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/7025963e-8e4a-4a93-90c7-d59d8494ea38/main.go b/code/7025963e-8e4a-4a93-90c7-d59d8494ea38/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/7025963e-8e4a-4a93-90c7-d59d8494ea38/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/73e8bd21-dcca-483a-8224-a023028c6891/main.go b/code/73e8bd21-dcca-483a-8224-a023028c6891/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/73e8bd21-dcca-483a-8224-a023028c6891/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/748ba15f-e625-480a-aed9-5c80ccbc2417/main.go b/code/748ba15f-e625-480a-aed9-5c80ccbc2417/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/748ba15f-e625-480a-aed9-5c80ccbc2417/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/74f14be1-1d7f-4eb6-8bb7-66e0c16422f6/main.go b/code/74f14be1-1d7f-4eb6-8bb7-66e0c16422f6/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/74f14be1-1d7f-4eb6-8bb7-66e0c16422f6/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/79f3a2da-5197-438e-9948-4f3fa05a21f5/main.go b/code/79f3a2da-5197-438e-9948-4f3fa05a21f5/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/79f3a2da-5197-438e-9948-4f3fa05a21f5/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/7b1eb8ac-8fa1-4976-823b-22cd3059e4b8/main.go b/code/7b1eb8ac-8fa1-4976-823b-22cd3059e4b8/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/7b1eb8ac-8fa1-4976-823b-22cd3059e4b8/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/80089deb-ff4c-4b5f-88b7-18973e49e16e/main.go b/code/80089deb-ff4c-4b5f-88b7-18973e49e16e/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/80089deb-ff4c-4b5f-88b7-18973e49e16e/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/87ad3870-15c5-4920-8f78-517ef85c43a7/main.go b/code/87ad3870-15c5-4920-8f78-517ef85c43a7/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/87ad3870-15c5-4920-8f78-517ef85c43a7/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/88c851a8-9add-4f1a-a38e-59ef9d0abf4e/main.go b/code/88c851a8-9add-4f1a-a38e-59ef9d0abf4e/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/88c851a8-9add-4f1a-a38e-59ef9d0abf4e/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/8ff8ecf3-62bf-4fb4-90f3-2ff10916c9d4/main.go b/code/8ff8ecf3-62bf-4fb4-90f3-2ff10916c9d4/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/8ff8ecf3-62bf-4fb4-90f3-2ff10916c9d4/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/95476d8f-99ad-4f8a-8564-aeb2847ca6bb/main.go b/code/95476d8f-99ad-4f8a-8564-aeb2847ca6bb/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/95476d8f-99ad-4f8a-8564-aeb2847ca6bb/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/999030bf-8eb6-4178-adbb-256fab98e796/main.go b/code/999030bf-8eb6-4178-adbb-256fab98e796/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/999030bf-8eb6-4178-adbb-256fab98e796/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/9c7af05b-6a03-4a0a-aeb8-353ea000c435/main.go b/code/9c7af05b-6a03-4a0a-aeb8-353ea000c435/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/9c7af05b-6a03-4a0a-aeb8-353ea000c435/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/9cc60fcb-4401-4bbf-99d2-1337d5133e76/main.go b/code/9cc60fcb-4401-4bbf-99d2-1337d5133e76/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/9cc60fcb-4401-4bbf-99d2-1337d5133e76/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/9e0330fc-c22c-41d8-a197-d476d2f87e84/main.go b/code/9e0330fc-c22c-41d8-a197-d476d2f87e84/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/9e0330fc-c22c-41d8-a197-d476d2f87e84/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/9e495e85-0992-4987-b32c-cfdbe8cee8ba/main.go b/code/9e495e85-0992-4987-b32c-cfdbe8cee8ba/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/9e495e85-0992-4987-b32c-cfdbe8cee8ba/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/a23ba488-f9cc-46de-923a-d113fc5b3f40/main.go b/code/a23ba488-f9cc-46de-923a-d113fc5b3f40/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/a23ba488-f9cc-46de-923a-d113fc5b3f40/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/a381c90d-fc6a-42d8-8e2f-7a502ff2f769/main.go b/code/a381c90d-fc6a-42d8-8e2f-7a502ff2f769/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/a381c90d-fc6a-42d8-8e2f-7a502ff2f769/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/a4a4564b-8599-424c-80da-83c5343d79ea/main.go b/code/a4a4564b-8599-424c-80da-83c5343d79ea/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/a4a4564b-8599-424c-80da-83c5343d79ea/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/ad3d4eb0-7afc-4b70-aa00-991e3da5be2b/main.go b/code/ad3d4eb0-7afc-4b70-aa00-991e3da5be2b/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/ad3d4eb0-7afc-4b70-aa00-991e3da5be2b/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/ad9538b6-0659-4b7a-96c2-3845c6b92fbe/main.go b/code/ad9538b6-0659-4b7a-96c2-3845c6b92fbe/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/ad9538b6-0659-4b7a-96c2-3845c6b92fbe/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/c03c47f7-4069-479a-9fe2-f915473c6997/main.go b/code/c03c47f7-4069-479a-9fe2-f915473c6997/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/c03c47f7-4069-479a-9fe2-f915473c6997/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/c7557548-e675-493d-94c4-73248303a918/main.go b/code/c7557548-e675-493d-94c4-73248303a918/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/c7557548-e675-493d-94c4-73248303a918/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/ca660014-e21a-41b0-b5ac-26ccb88a9c10/main.go b/code/ca660014-e21a-41b0-b5ac-26ccb88a9c10/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/ca660014-e21a-41b0-b5ac-26ccb88a9c10/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/cd4a099d-4f0d-45bc-9028-c601f3de68be/main.go b/code/cd4a099d-4f0d-45bc-9028-c601f3de68be/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/cd4a099d-4f0d-45bc-9028-c601f3de68be/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/code_user/main.go b/code/code_user/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/code_user/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/d7705570-39c9-4776-9ac0-6ff0b24e65a2/main.go b/code/d7705570-39c9-4776-9ac0-6ff0b24e65a2/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/d7705570-39c9-4776-9ac0-6ff0b24e65a2/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/daa08bd4-135f-4dca-a152-6aeb90afa938/main.go b/code/daa08bd4-135f-4dca-a152-6aeb90afa938/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/daa08bd4-135f-4dca-a152-6aeb90afa938/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/db7be0f4-17c2-4aa1-80a9-d45c9bf86da5/main.go b/code/db7be0f4-17c2-4aa1-80a9-d45c9bf86da5/main.go new file mode 100644 index 0000000..ab8eee4 --- /dev/null +++ b/code/db7be0f4-17c2-4aa1-80a9-d45c9bf86da5/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b+1) +} diff --git a/code/dcd15341-a8d5-4da8-9bfc-0455bc393231/main.go b/code/dcd15341-a8d5-4da8-9bfc-0455bc393231/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/dcd15341-a8d5-4da8-9bfc-0455bc393231/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/e2c24aed-8673-47ea-a93e-f968c88a6efc/main.go b/code/e2c24aed-8673-47ea-a93e-f968c88a6efc/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/e2c24aed-8673-47ea-a93e-f968c88a6efc/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/f8b6272d-d7cf-4d03-b06b-e9a125a8f549/main.go b/code/f8b6272d-d7cf-4d03-b06b-e9a125a8f549/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/f8b6272d-d7cf-4d03-b06b-e9a125a8f549/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/fc328f1d-3859-4a8b-b8e5-572521e4fdfb/main.go b/code/fc328f1d-3859-4a8b-b8e5-572521e4fdfb/main.go new file mode 100644 index 0000000..9b9e69a --- /dev/null +++ b/code/fc328f1d-3859-4a8b-b8e5-572521e4fdfb/main.go @@ -0,0 +1,10 @@ +package main + +import "fmt" + +// 两数之和 +func main() { + var a, b int + fmt.Scanln(&a, &b) + fmt.Println(a + b) +} diff --git a/code/runner.go b/code/runner.go new file mode 100644 index 0000000..09f4a8f --- /dev/null +++ b/code/runner.go @@ -0,0 +1,28 @@ +package main + +import ( + "bytes" + "fmt" + "io" + "log" + "os/exec" +) + +func main() { + cmd := exec.Command("go", "run", "C:\\Users\\linshengqian\\Desktop\\gin-gorm-oj\\code\\code_user\\main.go") + var out, stderr bytes.Buffer + cmd.Stderr = &stderr + cmd.Stdout = &out + stdinPipe, err := cmd.StdinPipe() + if err != nil { + log.Fatalln(err) + } + io.WriteString(stdinPipe, "23 11\n") + //根据测试的输入案例进行运行,拿到输出结果和标准输出结果进行比对 + if err = cmd.Run(); err != nil { + log.Fatalln(err) + } + fmt.Println(out.String()) + + println(out.String() == "34\n") +} diff --git a/define/define.go b/define/define.go new file mode 100644 index 0000000..2e9519d --- /dev/null +++ b/define/define.go @@ -0,0 +1,6 @@ +package define + +var ( + DefaultPage = "1" //默认页数 + DefaultSize = "20" +) diff --git a/docs/docs.go b/docs/docs.go new file mode 100644 index 0000000..23c8248 --- /dev/null +++ b/docs/docs.go @@ -0,0 +1,653 @@ +// Package docs Code generated by swaggo/swag. DO NOT EDIT +package docs + +import "github.com/swaggo/swag" + +const docTemplate = `{ + "schemes": {{ marshal .Schemes }}, + "swagger": "2.0", + "info": { + "description": "{{escape .Description}}", + "title": "{{.Title}}", + "contact": {}, + "version": "{{.Version}}" + }, + "host": "{{.Host}}", + "basePath": "{{.BasePath}}", + "paths": { + "/admin/category_create": { + "post": { + "tags": [ + "管理员私有方法" + ], + "summary": "分类的创建", + "parameters": [ + { + "type": "string", + "description": "authorization", + "name": "authorization", + "in": "header", + "required": true + }, + { + "type": "string", + "description": "name", + "name": "name", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "parentId", + "name": "parentId", + "in": "formData" + } + ], + "responses": { + "200": { + "description": "{\"code\":\"200\",\"list\":\"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/admin/category_delete": { + "delete": { + "tags": [ + "管理员私有方法" + ], + "summary": "分类的删除", + "parameters": [ + { + "type": "string", + "description": "authorization", + "name": "authorization", + "in": "header", + "required": true + }, + { + "type": "string", + "description": "identity", + "name": "identity", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "{\"code\":\"200\",\"data\":\"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/admin/category_list": { + "get": { + "tags": [ + "管理员私有方法" + ], + "summary": "分类列表", + "parameters": [ + { + "type": "string", + "description": "authorization", + "name": "authorization", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "第一页面", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "size", + "name": "size", + "in": "query" + }, + { + "type": "string", + "description": "keyword", + "name": "keyword", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\":\"200\",\"list\":\"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/admin/category_modify": { + "put": { + "tags": [ + "管理员私有方法" + ], + "summary": "分类的修改", + "parameters": [ + { + "type": "string", + "description": "authorization", + "name": "authorization", + "in": "header", + "required": true + }, + { + "type": "string", + "description": "identity", + "name": "identity", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "name", + "name": "name", + "in": "formData", + "required": true + }, + { + "type": "integer", + "description": "parentId", + "name": "parentId", + "in": "formData" + } + ], + "responses": { + "200": { + "description": "{\"code\":\"200\",\"data\":\"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/admin/problem_create": { + "post": { + "tags": [ + "管理员私有方法" + ], + "summary": "问题创建", + "parameters": [ + { + "type": "string", + "description": "authorization", + "name": "authorization", + "in": "header", + "required": true + }, + { + "type": "string", + "description": "title", + "name": "title", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "content", + "name": "content", + "in": "formData", + "required": true + }, + { + "type": "integer", + "description": "max_runtime", + "name": "max_runtime", + "in": "formData" + }, + { + "type": "integer", + "description": "max_mem", + "name": "max_mem", + "in": "formData" + }, + { + "type": "array", + "description": "category_ids", + "name": "category_ids", + "in": "formData" + }, + { + "type": "array", + "description": "test_cases", + "name": "test_cases", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "{\"code\":\"200\",\"list\":\"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/admin/problem_modify": { + "put": { + "tags": [ + "管理员私有方法" + ], + "summary": "问题修改", + "parameters": [ + { + "type": "string", + "description": "authorization", + "name": "authorization", + "in": "header", + "required": true + }, + { + "type": "string", + "description": "identity", + "name": "identity", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "title", + "name": "title", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "content", + "name": "content", + "in": "formData", + "required": true + }, + { + "type": "integer", + "description": "max_runtime", + "name": "max_runtime", + "in": "formData" + }, + { + "type": "integer", + "description": "max_mem", + "name": "max_mem", + "in": "formData" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "multi", + "description": "category_ids", + "name": "category_ids", + "in": "formData" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "multi", + "description": "test_cases", + "name": "test_cases", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "{\"code\":\"200\",\"list\":\"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/login": { + "post": { + "tags": [ + "公共方法" + ], + "summary": "用户登录", + "parameters": [ + { + "type": "string", + "description": "username", + "name": "username", + "in": "formData" + }, + { + "type": "string", + "description": "password", + "name": "password", + "in": "formData" + } + ], + "responses": { + "200": { + "description": "{\"code\":\"200\",\"list\":\"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/problem_detail": { + "get": { + "tags": [ + "公共方法" + ], + "summary": "问题详情", + "parameters": [ + { + "type": "string", + "description": "problem_identity", + "name": "identity", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\":\"200\",\"list\":\"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/problem_list": { + "get": { + "tags": [ + "公共方法" + ], + "summary": "问题列表", + "parameters": [ + { + "type": "integer", + "description": "第一页面", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "size", + "name": "size", + "in": "query" + }, + { + "type": "string", + "description": "keyword", + "name": "keyword", + "in": "query" + }, + { + "type": "string", + "description": "category_identity", + "name": "category_identity", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\":\"200\",\"list\":\"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/rank_list": { + "get": { + "tags": [ + "公共方法" + ], + "summary": "用户排行榜", + "parameters": [ + { + "type": "string", + "description": "page", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "size", + "name": "size", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\":\"200\",\"list\":\"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/register": { + "post": { + "tags": [ + "公共方法" + ], + "summary": "用户注册", + "parameters": [ + { + "type": "string", + "description": "mail", + "name": "mail", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "code", + "name": "code", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "name", + "name": "name", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "password", + "name": "password", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "phone", + "name": "phone", + "in": "formData" + } + ], + "responses": { + "200": { + "description": "{\"code\":\"200\",\"list\":\"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/send_code": { + "post": { + "tags": [ + "公共方法" + ], + "summary": "发送验证码", + "parameters": [ + { + "type": "string", + "description": "email", + "name": "email", + "in": "formData" + } + ], + "responses": { + "200": { + "description": "{\"code\":\"200\",\"list\":\"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/submit_list": { + "get": { + "tags": [ + "公共方法" + ], + "summary": "提交列表", + "parameters": [ + { + "type": "integer", + "description": "第一页面", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "size", + "name": "size", + "in": "query" + }, + { + "type": "string", + "description": "problem_identity", + "name": "problem_identity", + "in": "query" + }, + { + "type": "string", + "description": "user_identity", + "name": "user_identity", + "in": "query" + }, + { + "type": "integer", + "description": "status", + "name": "status", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\":\"200\",\"list\":\"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/user/submit": { + "post": { + "tags": [ + "用户私有方法" + ], + "summary": "代码提交", + "parameters": [ + { + "type": "string", + "description": "authorization", + "name": "authorization", + "in": "header", + "required": true + }, + { + "type": "string", + "description": "problem_identity", + "name": "problem_identity", + "in": "query", + "required": true + }, + { + "description": "code", + "name": "code", + "in": "body", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "{\"code\":\"200\",\"data\":\"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/user_detail": { + "get": { + "tags": [ + "公共方法" + ], + "summary": "用户详情", + "parameters": [ + { + "type": "string", + "description": "problem_identity", + "name": "identity", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\":\"200\",\"list\":\"\"}", + "schema": { + "type": "string" + } + } + } + } + } + } +}` + +// SwaggerInfo holds exported Swagger Info so clients can modify it +var SwaggerInfo = &swag.Spec{ + Version: "", + Host: "", + BasePath: "", + Schemes: []string{}, + Title: "", + Description: "", + InfoInstanceName: "swagger", + SwaggerTemplate: docTemplate, + LeftDelim: "{{", + RightDelim: "}}", +} + +func init() { + swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo) +} diff --git a/docs/swagger.json b/docs/swagger.json new file mode 100644 index 0000000..a7c1b89 --- /dev/null +++ b/docs/swagger.json @@ -0,0 +1,624 @@ +{ + "swagger": "2.0", + "info": { + "contact": {} + }, + "paths": { + "/admin/category_create": { + "post": { + "tags": [ + "管理员私有方法" + ], + "summary": "分类的创建", + "parameters": [ + { + "type": "string", + "description": "authorization", + "name": "authorization", + "in": "header", + "required": true + }, + { + "type": "string", + "description": "name", + "name": "name", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "parentId", + "name": "parentId", + "in": "formData" + } + ], + "responses": { + "200": { + "description": "{\"code\":\"200\",\"list\":\"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/admin/category_delete": { + "delete": { + "tags": [ + "管理员私有方法" + ], + "summary": "分类的删除", + "parameters": [ + { + "type": "string", + "description": "authorization", + "name": "authorization", + "in": "header", + "required": true + }, + { + "type": "string", + "description": "identity", + "name": "identity", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "{\"code\":\"200\",\"data\":\"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/admin/category_list": { + "get": { + "tags": [ + "管理员私有方法" + ], + "summary": "分类列表", + "parameters": [ + { + "type": "string", + "description": "authorization", + "name": "authorization", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "第一页面", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "size", + "name": "size", + "in": "query" + }, + { + "type": "string", + "description": "keyword", + "name": "keyword", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\":\"200\",\"list\":\"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/admin/category_modify": { + "put": { + "tags": [ + "管理员私有方法" + ], + "summary": "分类的修改", + "parameters": [ + { + "type": "string", + "description": "authorization", + "name": "authorization", + "in": "header", + "required": true + }, + { + "type": "string", + "description": "identity", + "name": "identity", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "name", + "name": "name", + "in": "formData", + "required": true + }, + { + "type": "integer", + "description": "parentId", + "name": "parentId", + "in": "formData" + } + ], + "responses": { + "200": { + "description": "{\"code\":\"200\",\"data\":\"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/admin/problem_create": { + "post": { + "tags": [ + "管理员私有方法" + ], + "summary": "问题创建", + "parameters": [ + { + "type": "string", + "description": "authorization", + "name": "authorization", + "in": "header", + "required": true + }, + { + "type": "string", + "description": "title", + "name": "title", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "content", + "name": "content", + "in": "formData", + "required": true + }, + { + "type": "integer", + "description": "max_runtime", + "name": "max_runtime", + "in": "formData" + }, + { + "type": "integer", + "description": "max_mem", + "name": "max_mem", + "in": "formData" + }, + { + "type": "array", + "description": "category_ids", + "name": "category_ids", + "in": "formData" + }, + { + "type": "array", + "description": "test_cases", + "name": "test_cases", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "{\"code\":\"200\",\"list\":\"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/admin/problem_modify": { + "put": { + "tags": [ + "管理员私有方法" + ], + "summary": "问题修改", + "parameters": [ + { + "type": "string", + "description": "authorization", + "name": "authorization", + "in": "header", + "required": true + }, + { + "type": "string", + "description": "identity", + "name": "identity", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "title", + "name": "title", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "content", + "name": "content", + "in": "formData", + "required": true + }, + { + "type": "integer", + "description": "max_runtime", + "name": "max_runtime", + "in": "formData" + }, + { + "type": "integer", + "description": "max_mem", + "name": "max_mem", + "in": "formData" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "multi", + "description": "category_ids", + "name": "category_ids", + "in": "formData" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "multi", + "description": "test_cases", + "name": "test_cases", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "{\"code\":\"200\",\"list\":\"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/login": { + "post": { + "tags": [ + "公共方法" + ], + "summary": "用户登录", + "parameters": [ + { + "type": "string", + "description": "username", + "name": "username", + "in": "formData" + }, + { + "type": "string", + "description": "password", + "name": "password", + "in": "formData" + } + ], + "responses": { + "200": { + "description": "{\"code\":\"200\",\"list\":\"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/problem_detail": { + "get": { + "tags": [ + "公共方法" + ], + "summary": "问题详情", + "parameters": [ + { + "type": "string", + "description": "problem_identity", + "name": "identity", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\":\"200\",\"list\":\"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/problem_list": { + "get": { + "tags": [ + "公共方法" + ], + "summary": "问题列表", + "parameters": [ + { + "type": "integer", + "description": "第一页面", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "size", + "name": "size", + "in": "query" + }, + { + "type": "string", + "description": "keyword", + "name": "keyword", + "in": "query" + }, + { + "type": "string", + "description": "category_identity", + "name": "category_identity", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\":\"200\",\"list\":\"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/rank_list": { + "get": { + "tags": [ + "公共方法" + ], + "summary": "用户排行榜", + "parameters": [ + { + "type": "string", + "description": "page", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "size", + "name": "size", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\":\"200\",\"list\":\"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/register": { + "post": { + "tags": [ + "公共方法" + ], + "summary": "用户注册", + "parameters": [ + { + "type": "string", + "description": "mail", + "name": "mail", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "code", + "name": "code", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "name", + "name": "name", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "password", + "name": "password", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "phone", + "name": "phone", + "in": "formData" + } + ], + "responses": { + "200": { + "description": "{\"code\":\"200\",\"list\":\"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/send_code": { + "post": { + "tags": [ + "公共方法" + ], + "summary": "发送验证码", + "parameters": [ + { + "type": "string", + "description": "email", + "name": "email", + "in": "formData" + } + ], + "responses": { + "200": { + "description": "{\"code\":\"200\",\"list\":\"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/submit_list": { + "get": { + "tags": [ + "公共方法" + ], + "summary": "提交列表", + "parameters": [ + { + "type": "integer", + "description": "第一页面", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "size", + "name": "size", + "in": "query" + }, + { + "type": "string", + "description": "problem_identity", + "name": "problem_identity", + "in": "query" + }, + { + "type": "string", + "description": "user_identity", + "name": "user_identity", + "in": "query" + }, + { + "type": "integer", + "description": "status", + "name": "status", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\":\"200\",\"list\":\"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/user/submit": { + "post": { + "tags": [ + "用户私有方法" + ], + "summary": "代码提交", + "parameters": [ + { + "type": "string", + "description": "authorization", + "name": "authorization", + "in": "header", + "required": true + }, + { + "type": "string", + "description": "problem_identity", + "name": "problem_identity", + "in": "query", + "required": true + }, + { + "description": "code", + "name": "code", + "in": "body", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "{\"code\":\"200\",\"data\":\"\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/user_detail": { + "get": { + "tags": [ + "公共方法" + ], + "summary": "用户详情", + "parameters": [ + { + "type": "string", + "description": "problem_identity", + "name": "identity", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\":\"200\",\"list\":\"\"}", + "schema": { + "type": "string" + } + } + } + } + } + } +} \ No newline at end of file diff --git a/docs/swagger.yaml b/docs/swagger.yaml new file mode 100644 index 0000000..2a05252 --- /dev/null +++ b/docs/swagger.yaml @@ -0,0 +1,408 @@ +info: + contact: {} +paths: + /admin/category_create: + post: + parameters: + - description: authorization + in: header + name: authorization + required: true + type: string + - description: name + in: formData + name: name + required: true + type: string + - description: parentId + in: formData + name: parentId + type: string + responses: + "200": + description: '{"code":"200","list":""}' + schema: + type: string + summary: 分类的创建 + tags: + - 管理员私有方法 + /admin/category_delete: + delete: + parameters: + - description: authorization + in: header + name: authorization + required: true + type: string + - description: identity + in: query + name: identity + required: true + type: string + responses: + "200": + description: '{"code":"200","data":""}' + schema: + type: string + summary: 分类的删除 + tags: + - 管理员私有方法 + /admin/category_list: + get: + parameters: + - description: authorization + in: header + name: authorization + required: true + type: string + - description: 第一页面 + in: query + name: page + type: integer + - description: size + in: query + name: size + type: integer + - description: keyword + in: query + name: keyword + type: string + responses: + "200": + description: '{"code":"200","list":""}' + schema: + type: string + summary: 分类列表 + tags: + - 管理员私有方法 + /admin/category_modify: + put: + parameters: + - description: authorization + in: header + name: authorization + required: true + type: string + - description: identity + in: formData + name: identity + required: true + type: string + - description: name + in: formData + name: name + required: true + type: string + - description: parentId + in: formData + name: parentId + type: integer + responses: + "200": + description: '{"code":"200","data":""}' + schema: + type: string + summary: 分类的修改 + tags: + - 管理员私有方法 + /admin/problem_create: + post: + parameters: + - description: authorization + in: header + name: authorization + required: true + type: string + - description: title + in: formData + name: title + required: true + type: string + - description: content + in: formData + name: content + required: true + type: string + - description: max_runtime + in: formData + name: max_runtime + type: integer + - description: max_mem + in: formData + name: max_mem + type: integer + - description: category_ids + in: formData + name: category_ids + type: array + - description: test_cases + in: formData + name: test_cases + required: true + type: array + responses: + "200": + description: '{"code":"200","list":""}' + schema: + type: string + summary: 问题创建 + tags: + - 管理员私有方法 + /admin/problem_modify: + put: + parameters: + - description: authorization + in: header + name: authorization + required: true + type: string + - description: identity + in: formData + name: identity + required: true + type: string + - description: title + in: formData + name: title + required: true + type: string + - description: content + in: formData + name: content + required: true + type: string + - description: max_runtime + in: formData + name: max_runtime + type: integer + - description: max_mem + in: formData + name: max_mem + type: integer + - collectionFormat: multi + description: category_ids + in: formData + items: + type: string + name: category_ids + type: array + - collectionFormat: multi + description: test_cases + in: formData + items: + type: string + name: test_cases + required: true + type: array + responses: + "200": + description: '{"code":"200","list":""}' + schema: + type: string + summary: 问题修改 + tags: + - 管理员私有方法 + /login: + post: + parameters: + - description: username + in: formData + name: username + type: string + - description: password + in: formData + name: password + type: string + responses: + "200": + description: '{"code":"200","list":""}' + schema: + type: string + summary: 用户登录 + tags: + - 公共方法 + /problem_detail: + get: + parameters: + - description: problem_identity + in: query + name: identity + type: string + responses: + "200": + description: '{"code":"200","list":""}' + schema: + type: string + summary: 问题详情 + tags: + - 公共方法 + /problem_list: + get: + parameters: + - description: 第一页面 + in: query + name: page + type: integer + - description: size + in: query + name: size + type: integer + - description: keyword + in: query + name: keyword + type: string + - description: category_identity + in: query + name: category_identity + type: string + responses: + "200": + description: '{"code":"200","list":""}' + schema: + type: string + summary: 问题列表 + tags: + - 公共方法 + /rank_list: + get: + parameters: + - description: page + in: query + name: page + type: string + - description: size + in: query + name: size + type: string + responses: + "200": + description: '{"code":"200","list":""}' + schema: + type: string + summary: 用户排行榜 + tags: + - 公共方法 + /register: + post: + parameters: + - description: mail + in: formData + name: mail + required: true + type: string + - description: code + in: formData + name: code + required: true + type: string + - description: name + in: formData + name: name + required: true + type: string + - description: password + in: formData + name: password + required: true + type: string + - description: phone + in: formData + name: phone + type: string + responses: + "200": + description: '{"code":"200","list":""}' + schema: + type: string + summary: 用户注册 + tags: + - 公共方法 + /send_code: + post: + parameters: + - description: email + in: formData + name: email + type: string + responses: + "200": + description: '{"code":"200","list":""}' + schema: + type: string + summary: 发送验证码 + tags: + - 公共方法 + /submit_list: + get: + parameters: + - description: 第一页面 + in: query + name: page + type: integer + - description: size + in: query + name: size + type: integer + - description: problem_identity + in: query + name: problem_identity + type: string + - description: user_identity + in: query + name: user_identity + type: string + - description: status + in: query + name: status + type: integer + responses: + "200": + description: '{"code":"200","list":""}' + schema: + type: string + summary: 提交列表 + tags: + - 公共方法 + /user/submit: + post: + parameters: + - description: authorization + in: header + name: authorization + required: true + type: string + - description: problem_identity + in: query + name: problem_identity + required: true + type: string + - description: code + in: body + name: code + required: true + schema: + type: string + responses: + "200": + description: '{"code":"200","data":""}' + schema: + type: string + summary: 代码提交 + tags: + - 用户私有方法 + /user_detail: + get: + parameters: + - description: problem_identity + in: query + name: identity + type: string + responses: + "200": + description: '{"code":"200","list":""}' + schema: + type: string + summary: 用户详情 + tags: + - 公共方法 +swagger: "2.0" diff --git a/gin-gorm-oj b/gin-gorm-oj new file mode 160000 index 0000000..56b53c3 --- /dev/null +++ b/gin-gorm-oj @@ -0,0 +1 @@ +Subproject commit 56b53c301f1f5f8054b17595bfbce3071a058540 diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..e67a869 --- /dev/null +++ b/go.mod @@ -0,0 +1,59 @@ +module lsq.com + +go 1.21 + +require ( + github.com/gin-gonic/gin v1.9.1 + github.com/golang-jwt/jwt/v4 v4.5.0 + github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible + github.com/swaggo/files v1.0.1 + github.com/swaggo/gin-swagger v1.6.0 + github.com/swaggo/swag v1.16.3 + gorm.io/driver/mysql v1.5.6 + gorm.io/gorm v1.25.9 +) + +require ( + filippo.io/edwards25519 v1.1.0 // indirect + github.com/KyleBanks/depth v1.2.1 // indirect + github.com/bytedance/sonic v1.11.3 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect + github.com/chenzhuoyu/iasm v0.9.1 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/gabriel-vasile/mimetype v1.4.3 // indirect + github.com/gin-contrib/sse v0.1.0 // indirect + github.com/go-openapi/jsonpointer v0.21.0 // indirect + github.com/go-openapi/jsonreference v0.21.0 // indirect + github.com/go-openapi/spec v0.21.0 // indirect + github.com/go-openapi/swag v0.23.0 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.19.0 // indirect + github.com/go-sql-driver/mysql v1.8.1 // indirect + github.com/goccy/go-json v0.10.2 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/cpuid/v2 v2.2.7 // indirect + github.com/leodido/go-urn v1.4.0 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/pelletier/go-toml/v2 v2.2.0 // indirect + github.com/redis/go-redis/v9 v9.5.1 // indirect + github.com/satori/go.uuid v1.2.0 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.2.12 // indirect + golang.org/x/arch v0.7.0 // indirect + golang.org/x/crypto v0.21.0 // indirect + golang.org/x/net v0.22.0 // indirect + golang.org/x/sys v0.18.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/tools v0.19.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..dc10cd4 --- /dev/null +++ b/go.sum @@ -0,0 +1,175 @@ +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= +github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= +github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= +github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM= +github.com/bytedance/sonic v1.11.3 h1:jRN+yEjakWh8aK5FzrciUHG8OFXK+4/KrAX/ysEtHAA= +github.com/bytedance/sonic v1.11.3/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= +github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0= +github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA= +github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= +github.com/chenzhuoyu/iasm v0.9.1 h1:tUHQJXo3NhBqw6s33wkGn9SP3bvrWLdlVIJ3hQBL7P0= +github.com/chenzhuoyu/iasm v0.9.1/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= +github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= +github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4= +github.com/gin-contrib/gzip v0.0.6/go.mod h1:QOJlmV2xmayAjkNS2Y8NQsMneuRShOU/kjovCXNuzzk= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= +github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= +github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= +github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= +github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= +github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= +github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY= +github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk= +github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= +github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.19.0 h1:ol+5Fu+cSq9JD7SoSqe04GMI92cbn0+wvQ3bZ8b/AU4= +github.com/go-playground/validator/v10 v10.19.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= +github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible h1:jdpOPRN1zP63Td1hDQbZW73xKmzDvZHzVdNYxhnTMDA= +github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible/go.mod h1:1c7szIrayyPPB/987hsnvNzLushdWf4o/79s3P08L8A= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= +github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pelletier/go-toml/v2 v2.2.0 h1:QLgLl2yMN7N+ruc31VynXs1vhMZa7CeHHejIeBAsoHo= +github.com/pelletier/go-toml/v2 v2.2.0/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/redis/go-redis/v9 v9.5.1 h1:H1X4D3yHPaYrkL5X06Wh6xNVM/pX0Ft4RV0vMGvLBh8= +github.com/redis/go-redis/v9 v9.5.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE= +github.com/swaggo/files v1.0.1/go.mod h1:0qXmMNH6sXNf+73t65aKeB+ApmgxdnkQzVTAj2uaMUg= +github.com/swaggo/gin-swagger v1.6.0 h1:y8sxvQ3E20/RCyrXeFfg60r6H0Z+SwpTjMYsMm+zy8M= +github.com/swaggo/gin-swagger v1.6.0/go.mod h1:BG00cCEy294xtVpyIAHG6+e2Qzj/xKlRdOqDkvq0uzo= +github.com/swaggo/swag v1.16.3 h1:PnCYjPCah8FK4I26l2F/KQ4yz3sILcVUN3cTlBFA9Pg= +github.com/swaggo/swag v1.16.3/go.mod h1:DImHIuOFXKpMFAQjcC7FG4m3Dg4+QuUgUzJmKjI/gRk= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= +github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc= +golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic= +golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= +golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw= +golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/driver/mysql v1.5.6 h1:Ld4mkIickM+EliaQZQx3uOJDJHtrd70MxAUqWqlx3Y8= +gorm.io/driver/mysql v1.5.6/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM= +gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= +gorm.io/gorm v1.25.9 h1:wct0gxZIELDk8+ZqF/MVnHLkA1rvYlBWUMv2EdsK1g8= +gorm.io/gorm v1.25.9/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= +nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/helper/helper.go b/helper/helper.go new file mode 100644 index 0000000..a53b4d3 --- /dev/null +++ b/helper/helper.go @@ -0,0 +1,115 @@ +package helper + +import ( + "crypto/md5" + "fmt" + "github.com/golang-jwt/jwt/v4" + "github.com/jordan-wright/email" + uuid "github.com/satori/go.uuid" + "math/rand" + "net/smtp" + "os" + "strconv" + "time" +) + +type UserClaims struct { + Identity string `json:"identity"` + Name string `json:"name"` + IsAdmin int `json:"is_admin"` + jwt.StandardClaims +} + +func GetMd5(s string) string { + return fmt.Sprintf("%x", md5.Sum([]byte(s))) +} + +// TODO 签名密钥 +var myKey = []byte("gin-gorm-oj-key") + +// GenerateToken +// TODO 生成token +func GenerateToken(identity, name string, isAdmin int) (string, error) { + UserClaims := &UserClaims{ + Identity: "user_1", + Name: "get", + IsAdmin: isAdmin, + StandardClaims: jwt.StandardClaims{ + //NotBefore: time.Now().Unix() - 60, // 令牌在当前时间的前60秒之前不生效 + //ExpiresAt: time.Now().Unix() + 5, // 令牌将在当前时间的后5秒过期 + Issuer: "lsq", // 令牌的发行者 + }, + } + //TODO 使用指定的签名方法和声明创建一个新的令牌 + token := jwt.NewWithClaims(jwt.SigningMethodHS256, UserClaims) + //TODO 使用签名密钥对令牌进行签名,并获取完整的签名后的令牌字符串 + tokenString, err := token.SignedString(myKey) + if err != nil { + return "", err + } + fmt.Println(tokenString) + return tokenString, nil + //eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZGVudGl0eSI6InVzZXJfMSIsIm5hbWUiOiJnZXQifQ.taKAmMZu6-6ioE4hSKqUgn9lHrqXSw-2TyEQTeNOreA +} + +// AnalyseToken +// 解析 token +func AnalyseToken(tokenString string) (*UserClaims, error) { + userClaim := new(UserClaims) + claims, err := jwt.ParseWithClaims(tokenString, userClaim, func(token *jwt.Token) (interface{}, error) { + return myKey, nil + }) + if err != nil { + return nil, err + } + if !claims.Valid { + return nil, fmt.Errorf("analyse Token Error:%v", err) + } + fmt.Println(claims) + return userClaim, nil +} + +// SendCode +// 发送验证码 +func SendCode(toUserEmail, code string) error { + e := email.NewEmail() + e.From = "Crayon <2993373191@qq.com>" + e.To = []string{toUserEmail} + e.Subject = "验证码已发送,请查收" + + e.HTML = []byte("

验证码:

" + code) + return e.Send("smtp.qq.com:587", smtp.PlainAuth("", "2993373191@qq.com", "vlkrwkqjayqedehc", "smtp.qq.com")) +} + +// GetUUID +func GetUUID() string { + return uuid.NewV4().String() +} + +// 生成验证码 +func GetRand() string { + rand.Seed(time.Now().UnixNano()) + s := "" + for i := 0; i < 6; i++ { + s += strconv.Itoa(rand.Intn(10)) + } + return s +} + +// CodeSave +// 保存代码 +func CodeSave(code []byte) (string, error) { + dirName := "code/" + GetUUID() + path := dirName + "/main.go" + err := os.Mkdir(dirName, 0777) + if err != nil { + return "", err + } + f, err := os.Create(path) + if err != nil { + return "", err + } + f.Write(code) + defer f.Close() + return path, nil +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..60765a3 --- /dev/null +++ b/main.go @@ -0,0 +1,9 @@ +package main + +import "lsq.com/router" + +func main() { + r := router.Router() + + r.Run() +} diff --git a/middlewares/auth_admin.go b/middlewares/auth_admin.go new file mode 100644 index 0000000..bac6bdd --- /dev/null +++ b/middlewares/auth_admin.go @@ -0,0 +1,32 @@ +package middlewares + +import ( + "github.com/gin-gonic/gin" + "lsq.com/helper" + "net/http" +) + +// AuthAdminCheck 验证用户是否是管理员 +func AuthAdminCheck() gin.HandlerFunc { + return func(c *gin.Context) { + auth := c.GetHeader("Authorization") + userClaim, err := helper.AnalyseToken(auth) + if err != nil { + c.Abort() + c.JSON(http.StatusOK, gin.H{ + "code": http.StatusUnauthorized, + "msg": "Unauthorized Authorization", + }) + return + } + if userClaim == nil || userClaim.IsAdmin != 1 { + c.Abort() + c.JSON(http.StatusOK, gin.H{ + "code": http.StatusUnauthorized, + "msg": "Unauthorized Admin", + }) + return + } + c.Next() + } +} diff --git a/middlewares/auth_user.go b/middlewares/auth_user.go new file mode 100644 index 0000000..9363717 --- /dev/null +++ b/middlewares/auth_user.go @@ -0,0 +1,35 @@ +package middlewares + +import ( + "fmt" + "github.com/gin-gonic/gin" + "lsq.com/helper" + "net/http" +) + +// AuthUserCheck +func AuthUserCheck() gin.HandlerFunc { + return func(c *gin.Context) { + auth := c.GetHeader("Authorization") + userClaim, err := helper.AnalyseToken(auth) + if err != nil { + c.Abort() + c.JSON(http.StatusOK, gin.H{ + "code": http.StatusUnauthorized, + "msg": "Unauthorized Authorization", + }) + return + } + if userClaim == nil { + c.Abort() + c.JSON(http.StatusOK, gin.H{ + "code": http.StatusUnauthorized, + "msg": "Unauthorized Admin", + }) + return + } + fmt.Println(userClaim) + c.Set("user_claims", userClaim) + c.Next() + } +} diff --git a/models/category_basic.go b/models/category_basic.go new file mode 100644 index 0000000..8b08af6 --- /dev/null +++ b/models/category_basic.go @@ -0,0 +1,16 @@ +package models + +import ( + "gorm.io/gorm" +) + +type CategoryBasic struct { + gorm.Model + Identity string `gorm:"column:identity;type:varchar(36);" json:"identity"` //分类表的唯一标识 + Name string `gorm:"column:name;type:varchar(100);" json:"name"` //分类名称 + ParentId int `gorm:"column:parent_id;type:int(11);" json:"parent_id"` //父类ID +} + +func (table *CategoryBasic) TableName() string { + return "category_basic" +} diff --git a/models/init.go b/models/init.go new file mode 100644 index 0000000..84fdd33 --- /dev/null +++ b/models/init.go @@ -0,0 +1,28 @@ +package models + +import ( + "github.com/redis/go-redis/v9" + "gorm.io/driver/mysql" + "gorm.io/gorm" + "log" +) + +var DB = Init() +var RDB = InitRedisDB() + +func Init() *gorm.DB { + dsn := "root:root@tcp(127.0.0.1:3306)/gin_gorm_oj?charset=utf8mb4&parseTime=True&loc=Local" + db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) + if err != nil { + log.Println("gorm Init Error", err) + } + return db +} +func InitRedisDB() *redis.Client { + return redis.NewClient(&redis.Options{ + Addr: "127.0.0.1:6379", + Password: "", // no password set + DB: 0, // use default DB + }) + +} diff --git a/models/problem_basic.go b/models/problem_basic.go new file mode 100644 index 0000000..d083bb2 --- /dev/null +++ b/models/problem_basic.go @@ -0,0 +1,33 @@ +package models + +import ( + "gorm.io/gorm" +) + +type ProblemBasic struct { + gorm.Model + Identity string `gorm:"column:identity;type:varchar(36);" json:"identity"` //问题表的唯一标识 + ProblemCategories []*ProblemCategory `gorm:"foreignKey:problem_id;references:id"` //关联问题分类表 + Title string `gorm:"column:title;type:varchar(255);" json:"title"` //文章标题 + Content string `gorm:"column:content;type:text;" json:"content"` //文章正文 + MaxRuntime int `gorm:"column:max_runtime;type:int(11);" json:"max_runtime"` //最大运行时间 + MaxMem int `gorm:"column:max_mem;type:int(11);" json:"max_mem"` //最大内存 + TestCase []*TestCase `gorm:"foreignKey:problem_identity;references:identity"` + PassNum int64 `gorm:"column:pass_num;type:int(11);" json:"pass_num"` //完成问题的个数 + SubmitNum int64 `gorm:"column:submit_num;type:int(11);" json:"submit_num"` //提交次数 + +} + +func (table *ProblemBasic) TableName() string { + return "problem_basic" +} +func GetProblemList(keyword, categoryIdentity string) *gorm.DB { + //指定查询的表 ,new(Problem)创建Problem模型实例 + tx := DB.Model(new(ProblemBasic)).Preload("ProblemCategories").Preload("ProblemCategories.CategoryBasic"). + Where("title like ? OR content like ?", "%"+keyword+"%", "%"+keyword+"%") + if categoryIdentity != "" { + tx.Joins("RIGHT JOIN problem_category pc on pc.problem_id=problem_basic.id"). + Where("pc.category_id =(SELECT cb.id FROM category_basic cb WHERE cb.identity=?)", categoryIdentity) + } + return tx +} diff --git a/models/problem_category.go b/models/problem_category.go new file mode 100644 index 0000000..6e3ea32 --- /dev/null +++ b/models/problem_category.go @@ -0,0 +1,16 @@ +package models + +import ( + "gorm.io/gorm" +) + +type ProblemCategory struct { + gorm.Model + ProblemId uint `gorm:"column:problem_id;type:varchar(36);" json:"problem_id"` // 问题的ID + CategoryId uint `gorm:"column:category_id;type:varchar(36);" json:"category_id"` // 分类的ID + CategoryBasic *CategoryBasic `gorm:"foreignKey:id;references:category_id;" json:"category_basic"` // 关联分类的基础信息表 +} + +func (table *ProblemCategory) TableName() string { + return "problem_category" +} diff --git a/models/submit_basic.go b/models/submit_basic.go new file mode 100644 index 0000000..2a47a04 --- /dev/null +++ b/models/submit_basic.go @@ -0,0 +1,35 @@ +package models + +import "gorm.io/gorm" + +type SubmitBasic struct { + gorm.Model + Identity string `gorm:"column:identity;type:varchar(36);" json:"identity"` //提交表的唯一标识 + ProblemIdentity string `gorm:"column:problem_identity;type:varchar(36);" json:"problem_identity"` //问题表的唯一标识 + ProblemBasic *ProblemBasic `gorm:"foreignKey:identity;references:problem_identity"` //关联问题基础表 + UserIdentity string `gorm:"column:user_identity;type:varchar(32);" json:"user_identity"` //用户表的唯一标识密码 + UserBasic *UserBasic `gorm:"foreignKey:identity;references:user_identity"` //关联用户基础表 + Path string `gorm:"column:path;type:varchar(255);" json:"path"` //代码存放路径 + Status int `gorm:"column:status;type:tinyint(1);" json:"status"` //[-1-待判断,1-答案正确,2-答案错误,3-运行超时,4-运行超内存,5-编译错误] +} + +func (table *SubmitBasic) TableName() string { + return "submit_basic" +} + +func GetSubmitList(problemIdentity, userIdentity string, status int) *gorm.DB { + //Model(new(SubmitBasic))指定了查询操作的目标模型为 SubmitBasic + tx := DB.Model(new(SubmitBasic)).Preload("ProblemBasic", func(db *gorm.DB) *gorm.DB { + return db.Omit("content") + }).Preload("UserBasic") + if problemIdentity != "" { + tx.Where("problem_identity=?", problemIdentity) + } + if userIdentity != "" { + tx.Where("user_identity=?", userIdentity) + } + if status != 0 { + tx.Where("status=?", status) + } + return tx +} diff --git a/models/test_case.go b/models/test_case.go new file mode 100644 index 0000000..1462653 --- /dev/null +++ b/models/test_case.go @@ -0,0 +1,15 @@ +package models + +import "gorm.io/gorm" + +type TestCase struct { + gorm.Model + Identity string `gorm:"column:identity;type:varchar(36);" json:"identity"` //用户表的唯一标识 + ProblemIdentity string `gorm:"column:problem_identity;type:varchar(36);" json:"problem_identity"` //用户名 + Input string `gorm:"column:input;type:text;" json:"input"` //密码 + Output string `gorm:"column:output;type:text;" json:"output"` +} + +func (table *TestCase) TableName() string { + return "test_case" +} diff --git a/models/user_basic.go b/models/user_basic.go new file mode 100644 index 0000000..cd6dbab --- /dev/null +++ b/models/user_basic.go @@ -0,0 +1,21 @@ +package models + +import ( + "gorm.io/gorm" +) + +type UserBasic struct { + gorm.Model + Identity string `gorm:"column:identity;type:varchar(36);" json:"identity"` //用户表的唯一标识 + Name string `gorm:"column:name;type:varchar(100);" json:"name"` //用户名 + Password string `gorm:"column:password;type:varchar(32);" json:"password"` //密码 + Phone string `gorm:"column:phone;type:varchar(20);" json:"phone"` //手机号 + Mail string `gorm:"column:mail;type:varchar(100);" json:"mail"` //邮箱 + PassNum int64 `gorm:"column:pass_num;type:int(11);" json:"pass_num"` //完成问题的个数 + SubmitNum int64 `gorm:"column:submit_num;type:int(11);" json:"submit_num"` //提交次数 + IsAdmin int `gorm:"column:is_admin;type:tinyint(1);" json:"is_admin"` //是否是管理员[0不是,1是] +} + +func (table *UserBasic) TableName() string { + return "user_basic" +} diff --git a/router/app.go b/router/app.go new file mode 100644 index 0000000..c6d7dea --- /dev/null +++ b/router/app.go @@ -0,0 +1,56 @@ +package router + +import ( + "github.com/gin-gonic/gin" + swaggerfiles "github.com/swaggo/files" + ginSwagger "github.com/swaggo/gin-swagger" + _ "lsq.com/docs" + "lsq.com/middlewares" + "lsq.com/service" +) + +func Router() *gin.Engine { + r := gin.Default() + + //swag 配置 + r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerfiles.Handler)) + + //公有方法 + //问题 + r.GET("/problem_list", service.GetProblemList) + r.GET("/problem_detail", service.GetProblemDetail) + + //用户 + r.GET("/user_detail", service.GetUserDetailAll) + r.POST("/login", service.Login) + r.POST("/send_code", service.SendCode) + r.POST("/register", service.Register) + //用户排行榜 + r.GET("/rank_list", service.GetRankList) + + //提交记录 + r.GET("/submit_list", service.GetSubmitList) + + //管理员私有方法 + authAdmin := r.Group("/admin", middlewares.AuthAdminCheck()) + //问题创建 + authAdmin.POST("/problem_create", service.ProblemCreate) + //问题修改 + authAdmin.PUT("/problem_modify", service.ProblemModify) + //分类列表 + authAdmin.GET("/category_list", service.GetCategoryList) + //分类的创建 + authAdmin.POST("/category_create", service.GetCategoryCreate) + //分类的修改 + authAdmin.PUT("/category_modify", service.GetCategoryModify) + //分类的删除 + authAdmin.DELETE("/category_delete", service.GetCategoryDelete) + + //用户私有方法 + authUser := r.Group("/user", middlewares.AuthUserCheck()) + //代码提交 + authUser.POST("/submit", service.Submit) + + return r + +} diff --git a/service/category.go b/service/category.go new file mode 100644 index 0000000..d18f93b --- /dev/null +++ b/service/category.go @@ -0,0 +1,170 @@ +package service + +import ( + "github.com/gin-gonic/gin" + "log" + "lsq.com/define" + "lsq.com/helper" + "lsq.com/models" + "net/http" + "strconv" +) + +// GetCategoryList +// @Tags 管理员私有方法 +// @Summary 分类列表 +// @Param authorization header string true "authorization" +// @Param page query int false "第一页面" +// @Param size query int false "size" +// @Param keyword query string false "keyword" +// @Success 200 {string} json "{"code":"200","list":""}" +// @Router /admin/category_list [get] +func GetCategoryList(c *gin.Context) { + size, _ := strconv.Atoi(c.DefaultQuery("size", define.DefaultSize)) + page, err := strconv.Atoi(c.DefaultQuery("page", define.DefaultPage)) + if err != nil { + log.Println("Get ProblemList Page strconv Error:", err) + return + } + //page == 1 ===> offset 0 + page = (page - 1) * size + var count int64 + keyword := c.Query("keyword") + categoryList := make([]*models.CategoryBasic, 0) + err = models.DB.Model(new(models.CategoryBasic)).Where("name like ?", "%"+keyword+"%"). + Count(&count).Limit(size).Offset(page).Find(&categoryList).Error + if err != nil { + log.Println("GetCategoryList Error:", err) + c.JSON(http.StatusOK, gin.H{ + "code": 200, + "msg": "获取分类列表失败", + }) + return + } + c.JSON(http.StatusOK, gin.H{ + "code": 200, + "data": map[string]interface{}{ + "list": categoryList, + "count": count, + }, + }) +} + +// GetCategoryCreate +// @Tags 管理员私有方法 +// @Summary 分类的创建 +// @Param authorization header string true "authorization" +// @Param name formData string true "name" +// @Param parentId formData string false "parentId" +// @Success 200 {string} json "{"code":"200","list":""}" +// @Router /admin/category_create [post] +func GetCategoryCreate(c *gin.Context) { + name := c.PostForm("name") + parentId, _ := strconv.Atoi(c.PostForm("parentId")) + category := &models.CategoryBasic{ + Identity: helper.GetUUID(), + Name: name, + ParentId: parentId, + } + err := models.DB.Create(category).Error + if err != nil { + log.Println("CategoryCreate Error:", err) + c.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": "创建分类失败", + }) + return + } + c.JSON(http.StatusOK, gin.H{ + "code": 200, + "msg": "创建成功", + }) +} + +// GetCategoryModify +// @Tags 管理员私有方法 +// @Summary 分类的修改 +// @Param authorization header string true "authorization" +// @Param identity formData string true "identity" +// @Param name formData string true "name" +// @Param parentId formData int false "parentId" +// @Success 200 {string} json "{"code":"200","data":""}" +// @Router /admin/category_modify [put] +func GetCategoryModify(c *gin.Context) { + identity := c.PostForm("identity") + name := c.PostForm("name") + parentId, _ := strconv.Atoi(c.PostForm("parentId")) + if name == "" || identity == "" { + c.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": "参数不正确", + }) + return + } + category := &models.CategoryBasic{ + Identity: identity, + Name: name, + ParentId: parentId, + } + err := models.DB.Model(new(models.CategoryBasic)).Where("identity = ?", identity).Updates(category).Error + if err != nil { + log.Println("CategoryModify Error:", err) + c.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": "修改分类失败", + }) + return + } + c.JSON(http.StatusOK, gin.H{ + "code": 200, + "msg": "修改成功", + }) +} + +// GetCategoryDelete +// @Tags 管理员私有方法 +// @Summary 分类的删除 +// @Param authorization header string true "authorization" +// @Param identity query string true "identity" +// @Success 200 {string} json "{"code":"200","data":""}" +// @Router /admin/category_delete [delete] +func GetCategoryDelete(c *gin.Context) { + identity := c.Query("identity") + if identity == "" { + c.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": "参数不正确", + }) + return + } + var cnt int64 + err := models.DB.Model(new(models.ProblemCategory)).Where("category_id = (SELECT id FROM category_basic WHERE identity = ? LIMIT 1)", identity).Count(&cnt).Error + if err != nil { + log.Println("Get ProblemCategory Error:", err) + c.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": "获取分类关联的问题失败", + }) + return + } + if cnt > 0 { + c.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": "该分类下面已存在问题,不可删除", + }) + return + } + err = models.DB.Where("identity = ?", identity).Delete(new(models.CategoryBasic)).Error + if err != nil { + log.Println("Delete CategoryBasic Error:", err) + c.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": "删除失败", + }) + return + } + c.JSON(http.StatusOK, gin.H{ + "code": 200, + "msg": "删除成功", + }) +} diff --git a/service/problem.go b/service/problem.go new file mode 100644 index 0000000..6a47364 --- /dev/null +++ b/service/problem.go @@ -0,0 +1,310 @@ +package service + +import ( + "encoding/json" + "errors" + "github.com/gin-gonic/gin" + "gorm.io/gorm" + "log" + "lsq.com/define" + "lsq.com/helper" + "lsq.com/models" + "net/http" + "strconv" +) + +// GetProblemList +// @Tags 公共方法 +// @Summary 问题列表 +// @Param page query int false "第一页面" +// @Param size query int false "size" +// @Param keyword query string false "keyword" +// @Param category_identity query string false "category_identity" +// @Success 200 {string} json "{"code":"200","list":""}" +// @Router /problem_list [get] +func GetProblemList(c *gin.Context) { + //字符串转换为整数 + size, _ := strconv.Atoi(c.DefaultQuery("size", define.DefaultSize)) + page, err := strconv.Atoi(c.DefaultQuery("page", define.DefaultPage)) + if err != nil { + log.Println("Get ProblemList Page strconv Error:", err) + return + } + //page == 1 ===> offset 0 + page = (page - 1) * size + var count int64 + keyword := c.Query("keyword") + categoryIdentity := c.Query("category_identity") + + //创建一个切片存储models.Problem类型的元素 + list := make([]*models.ProblemBasic, 0) + tx := models.GetProblemList(keyword, categoryIdentity) + //Offset起始位置;Limit每页的数据个数;Find查询的数据映射到struct + //Omit(): 查询结果中排除了xxx字段 + err = tx.Count(&count).Omit("content").Offset(page).Limit(size).Find(&list).Error + if err != nil { + log.Println("Get Problem List Error:", err) + return + } + + c.JSON(http.StatusOK, gin.H{ + "code": 200, + "data": map[string]interface{}{ + "list": list, + "count": count, + }, + }) +} + +// GetProblemDetail +// @Tags 公共方法 +// @Summary 问题详情 +// @Param identity query string false "problem_identity" +// @Success 200 {string} json "{"code":"200","list":""}" +// @Router /problem_detail [get] +func GetProblemDetail(c *gin.Context) { + identity := c.Query("identity") + if identity == "" { + c.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": "问题唯一标识不能为空", + }) + return + } + data := new(models.ProblemBasic) + err := models.DB.Where("identity = ?", identity). + Preload("ProblemCategories"). + Preload("ProblemCategories.CategoryBasic"). + First(&data).Error + if err != nil { + if err == gorm.ErrRecordNotFound { + c.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": "问题不存在", + }) + return + } + c.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": "Get ProblemDetail Error:" + err.Error(), + }) + return + } + c.JSON(http.StatusOK, gin.H{ + "code": -1, + "data": data, + }) +} + +// ProblemCreate +// @Tags 管理员私有方法 +// @Summary 问题创建 +// @Param authorization header string true "authorization" +// @Param title formData string true "title" +// @Param content formData string true "content" +// @Param max_runtime formData int false "max_runtime" +// @Param max_mem formData int false "max_mem" +// @Param category_ids formData array false "category_ids" +// @Param test_cases formData array true "test_cases" +// @Success 200 {string} json "{"code":"200","list":""}" +// @Router /admin/problem_create [post] +func ProblemCreate(c *gin.Context) { + title := c.PostForm("title") + content := c.PostForm("content") + maxRuntime, _ := strconv.Atoi(c.PostForm("max_runtime")) + maxMem, _ := strconv.Atoi(c.PostForm("max_mem")) + categoryIds := c.PostFormArray("category_ids") + testCases := c.PostFormArray("test_cases") + if title == "" || content == "" || len(testCases) == 0 { + c.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": "参数不能为空", + }) + return + } + identity := helper.GetUUID() + data := &models.ProblemBasic{ + Identity: identity, + Title: title, + Content: content, + MaxRuntime: maxRuntime, + MaxMem: maxMem, + } + //处理分类 + categoryBasics := make([]*models.ProblemCategory, 0) + for _, id := range categoryIds { + categoryId, _ := strconv.Atoi(id) + categoryBasics = append(categoryBasics, &models.ProblemCategory{ + ProblemId: data.ID, + CategoryId: uint(categoryId), + }) + } + data.ProblemCategories = categoryBasics + + //处理测试用例 + testCaseBasics := make([]*models.TestCase, 0) + for _, testCase := range testCases { + caseMap := make(map[string]string) + err := json.Unmarshal([]byte(testCase), &caseMap) + if err != nil { + c.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": "测试用例格式错误1", + }) + return + } + if _, ok := caseMap["input"]; !ok { + c.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": "测试用例格式错误2", + }) + return + } + if _, ok := caseMap["output"]; !ok { + c.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": "测试用例格式错误3", + }) + return + } + testCaseBasic := &models.TestCase{ + Identity: helper.GetUUID(), + ProblemIdentity: identity, + Input: caseMap["input"], + Output: caseMap["Output"], + } + testCaseBasics = append(testCaseBasics, testCaseBasic) + } + data.TestCase = testCaseBasics + + //创建问题 + err := models.DB.Create(data).Error + if err != nil { + c.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": "Problem Create Error:" + err.Error(), + }) + return + } + c.JSON(http.StatusOK, gin.H{ + "code": 200, + "data": map[string]interface{}{ + "identity": data.Identity, + }, + }) + +} + +// ProblemModify +// @Tags 管理员私有方法 +// @Summary 问题修改 +// @Param authorization header string true "authorization" +// @Param identity formData string true "identity" +// @Param title formData string true "title" +// @Param content formData string true "content" +// @Param max_runtime formData int false "max_runtime" +// @Param max_mem formData int false "max_mem" +// @Param category_ids formData []string false "category_ids" collectionFormat(multi) +// @Param test_cases formData []string true "test_cases" collectionFormat(multi) +// @Success 200 {string} json "{"code":"200","list":""}" +// @Router /admin/problem_modify [put] +func ProblemModify(c *gin.Context) { + identity := c.PostForm("identity") + content := c.PostForm("content") + title := c.PostForm("title") + maxRuntime, _ := strconv.Atoi(c.PostForm("max_runtime")) + maxMem, _ := strconv.Atoi(c.PostForm("max_mem")) + categoryIds := c.PostFormArray("category_ids") + testCases := c.PostFormArray("test_cases") + if identity == "" || title == "" || content == "" || len(categoryIds) == 0 || len(testCases) == 0 || maxRuntime == 0 || maxMem == 0 { + c.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": "参数不能为空", + }) + return + } + if err := models.DB.Transaction(func(tx *gorm.DB) error { + //问题基础信息保存 problemBasic + problemBasic := &models.ProblemBasic{ + Identity: identity, + Title: title, + Content: content, + MaxRuntime: maxRuntime, + MaxMem: maxMem, + } + err := tx.Where("identity = ?", identity).Updates(problemBasic).Error + if err != nil { + return err + } + //查询问题详情 + err = tx.Where("identity = ?", identity).Find(problemBasic).Error + if err != nil { + return err + } + //关联问题分类的更新 + //1.删除已存在的关联关系 + err = tx.Where("problem_id = ?", problemBasic.ID).Delete(new(models.ProblemCategory)).Error + if err != nil { + return err + } + //2.新增关联关系 + pcs := make([]*models.ProblemCategory, 0) + for _, id := range categoryIds { + intId, _ := strconv.Atoi(id) + pcs = append(pcs, &models.ProblemCategory{ + ProblemId: problemBasic.ID, + CategoryId: uint(intId), + }) + } + err = tx.Create(&pcs).Error + if err != nil { + return err + } + + //关联测试案例的更新 + // 1、删除已存在的关联关系 + err = tx.Where("problem_identity = ?", identity).Delete(new(models.TestCase)).Error + if err != nil { + return err + } + // 2、增加新的关联关系 + tcs := make([]*models.TestCase, 0) + caseMap := make(map[string]string, 0) + for _, testCases := range testCases { + err := json.Unmarshal([]byte(testCases), &caseMap) + if err != nil { + return err + } + if _, ok := caseMap["input"]; !ok { + return errors.New("测试案例[input]格式错误") + } + if _, ok := caseMap["output"]; !ok { + return errors.New("测试案例[output]格式错误") + } + // 举个例子 {"input":"1 2\n","output":"3\n"} + tcs = append(tcs, &models.TestCase{ + Identity: helper.GetUUID(), + ProblemIdentity: identity, + Input: caseMap["input"], + Output: caseMap["output"], + }) + } + err = tx.Create(tcs).Error + if err != nil { + return err + } + return nil + }); err != nil { + c.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": "Problem Modify Error" + err.Error(), + }) + return + } + c.JSON(http.StatusOK, gin.H{ + "code": 200, + "msg": "问题修改成功", + }) + return + +} diff --git a/service/submit.go b/service/submit.go new file mode 100644 index 0000000..1d7670f --- /dev/null +++ b/service/submit.go @@ -0,0 +1,239 @@ +package service + +import ( + "bytes" + "errors" + "fmt" + "github.com/gin-gonic/gin" + "gorm.io/gorm" + "io" + "io/ioutil" + "log" + "lsq.com/define" + "lsq.com/helper" + "lsq.com/models" + "net/http" + "os/exec" + "runtime" + "strconv" + "sync" + "time" +) + +// GetSubmitList +// @Tags 公共方法 +// @Summary 提交列表 +// @Param page query int false "第一页面" +// @Param size query int false "size" +// @Param problem_identity query string false "problem_identity" +// @Param user_identity query string false "user_identity" +// @Param status query int false "status" +// @Success 200 {string} json "{"code":"200","list":""}" +// @Router /submit_list [get] +func GetSubmitList(c *gin.Context) { + //字符串转换为整数 + size, _ := strconv.Atoi(c.DefaultQuery("size", define.DefaultSize)) + page, err := strconv.Atoi(c.DefaultQuery("page", define.DefaultPage)) + if err != nil { + log.Println("Get ProblemList Page strconv Error:", err) + return + } + //page == 1 ===> offset 0 + page = (page - 1) * size + + var count int64 + list := make([]models.SubmitBasic, 0) + + problemIdentity := c.Query("problem_identity") + userIdentity := c.Query("user_identity") + status, _ := strconv.Atoi(c.Query("status")) + tx := models.GetSubmitList(problemIdentity, userIdentity, status) + err = tx.Count(&count).Offset(page).Limit(size).Find(&list).Error + if err != nil { + log.Println("Get Problem List List Error:", err) + c.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": "Get Submit List Error:" + err.Error(), + }) + return + } + c.JSON(http.StatusOK, gin.H{ + "code": 200, + "data": map[string]interface{}{ + "list": list, + "count": count, + }, + }) +} + +// Submit +// @Tags 用户私有方法 +// @Summary 代码提交 +// @Param authorization header string true "authorization" +// @Param problem_identity query string true "problem_identity" +// @Param code body string true "code" +// @Success 200 {string} json "{"code":"200","data":""}" +// @Router /user/submit [post] +func Submit(c *gin.Context) { + problemIdentity := c.Query("problem_identity") + code, err := ioutil.ReadAll(c.Request.Body) + if err != nil { + c.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": "Read Code Error:" + err.Error(), + }) + return + } + // 代码保存 + path, err := helper.CodeSave(code) + if err != nil { + c.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": "Code Save Error:" + err.Error(), + }) + return + } + u, _ := c.Get("user_claims") + userClaim := u.(*helper.UserClaims) + sb := &models.SubmitBasic{ + Identity: helper.GetUUID(), + ProblemIdentity: problemIdentity, + UserIdentity: userClaim.Identity, + Path: path, + } + // 代码判断 + pb := new(models.ProblemBasic) + err = models.DB.Where("identity = ?", problemIdentity).Preload("TestCase").First(pb).Error + if err != nil { + c.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": "Get Problem Error:" + err.Error(), + }) + return + } + // 答案错误的channel + WA := make(chan int) + // 超内存的channel + OOM := make(chan int) + // 编译错误的channel + CE := make(chan int) + // 答案正确的channel + AC := make(chan int) + // 非法代码的channel + EC := make(chan struct{}) + + // 通过的个数 + passCount := 0 + var lock sync.Mutex + // 提示信息 + var msg string + + for _, testCase := range pb.TestCase { + testCase := testCase + go func() { + cmd := exec.Command("go", "run", path) + var out, stderr bytes.Buffer + cmd.Stderr = &stderr + cmd.Stdout = &out + stdinPipe, err := cmd.StdinPipe() + if err != nil { + log.Fatalln(err) + } + io.WriteString(stdinPipe, testCase.Input) //todo +"\n" + + var bm runtime.MemStats + runtime.ReadMemStats(&bm) + //根据测试的输入案例进行运行,拿到输出结果和标准输出结果进行比对 + if err = cmd.Run(); err != nil { + log.Println(err, stderr.String()) + if err.Error() == "exit status 2" { + msg = stderr.String() + CE <- 1 + return + } + } + var em runtime.MemStats + runtime.ReadMemStats(&em) + //答案错误 + fmt.Println("===testCase=" + testCase.Output + "==testCase==") + fmt.Println("==out==" + out.String() + "==out==") + if testCase.Output != out.String() { + msg = "答案错误" + WA <- 1 + return + } + //运行超内存 + if em.Alloc/1024-(bm.Alloc/1024) > uint64(pb.MaxMem) { + msg = "运行超内存" + OOM <- 1 + return + } + lock.Lock() + passCount++ + if passCount == len(pb.TestCase) { + AC <- 1 + } + lock.Unlock() + }() + } + select { + case <-EC: + msg = "无效代码" + sb.Status = 6 + case <-WA: + msg = "答案错误" + sb.Status = 2 + case <-OOM: + msg = "运行超内存" + sb.Status = 4 + case <-CE: + sb.Status = 5 + case <-AC: + msg = "答案正确" + sb.Status = 1 + case <-time.After(time.Millisecond * time.Duration(pb.MaxRuntime)): + if passCount == len(pb.TestCase) { + sb.Status = 1 + msg = "答案正确" + } else { + sb.Status = 3 + msg = "运行超时" + } + } + + if err = models.DB.Transaction(func(tx *gorm.DB) error { + err = models.DB.Create(sb).Error + if err != nil { + return errors.New("SubmitBasic Save Error:" + err.Error()) + } + m := make(map[string]interface{}) + m["submit_num"] = gorm.Expr("submit_num + ?", 1) + if sb.Status == 1 { + m["pass_num"] = gorm.Expr("pass_num + ?", 1) + } + //更新user_basic + err = tx.Model(new(models.UserBasic)).Where("identity = ?", userClaim.Identity).Updates(m).Error + if err != nil { + return errors.New("UserBasic Modify Error:" + err.Error()) + } + //更新problem_basic + err = tx.Model(new(models.ProblemBasic)).Where("identity = ?", problemIdentity).Updates(m).Error + if err != nil { + return errors.New("ProblemBasic Modify Error:" + err.Error()) + } + return nil + }); err != nil { + c.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": "Submit Error:" + err.Error(), + }) + return + } + c.JSON(http.StatusOK, gin.H{ + "code": 200, + "data": map[string]interface{}{ + "status": sb.Status, + "msg": msg, + }, + }) +} diff --git a/service/user.go b/service/user.go new file mode 100644 index 0000000..cc3a90a --- /dev/null +++ b/service/user.go @@ -0,0 +1,255 @@ +package service + +import ( + "github.com/gin-gonic/gin" + "gorm.io/gorm" + "log" + "lsq.com/define" + "lsq.com/helper" + "lsq.com/models" + "net/http" + "strconv" + "time" +) + +// GetUserDetailAll +// @Tags 公共方法 +// @Summary 用户详情 +// @Param identity query string false "problem_identity" +// @Success 200 {string} json "{"code":"200","list":""}" +// @Router /user_detail [get] +func GetUserDetailAll(c *gin.Context) { + identity := c.Query("identity") + if identity == "" { + c.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": "用户唯一标识不能为空", + }) + return + } + data := new(models.UserBasic) + err := models.DB.Omit("password").Where("identity = ?", identity).Find(&data).Error + if err != nil { + c.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": "Get User Detail Identity:" + identity + "Error" + err.Error(), + }) + return + } + c.JSON(http.StatusOK, gin.H{ + "code": 200, + "data": data, + }) +} + +// Login +// @Tags 公共方法 +// @Summary 用户登录 +// @Param username formData string false "username" +// @Param password formData string false "password" +// @Success 200 {string} json "{"code":"200","list":""}" +// @Router /login [post] +func Login(c *gin.Context) { + username := c.PostForm("username") + password := c.PostForm("password") + if username == "" || password == "" { + c.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": "必填信息为空", + }) + } + //md5 + password = helper.GetMd5(password) + data := new(models.UserBasic) + err := models.DB.Where("name=? AND password = ?", username, password).Find(&data).Error + if err != nil { + if err == gorm.ErrRecordNotFound { + c.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": "用户名或密码错误", + }) + return + } + c.JSON(http.StatusOK, gin.H{ + "code": 200, + "msg": "Get UserBasic Error:" + err.Error(), + }) + return + } + + token, err := helper.GenerateToken(data.Identity, data.Name, data.IsAdmin) + if err != nil { + c.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": "GenerateToken Error:" + err.Error(), + }) + } + + c.JSON(http.StatusOK, gin.H{ + "code": 200, + "data": map[string]interface{}{ + "token": token, + }, + }) + +} + +// SendCode +// @Tags 公共方法 +// @Summary 发送验证码 +// @Param email formData string false "email" +// @Success 200 {string} json "{"code":"200","list":""}" +// @Router /send_code [post] +func SendCode(c *gin.Context) { + email := c.PostForm("email") + if email == "" { + c.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": "参数不正确", + }) + return + } + //TODO + code := helper.GetRand() + models.RDB.Set(c, email, code, time.Second*300) + err := helper.SendCode(email, code) + if err != nil { + c.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": "Send Code Error:" + err.Error(), + }) + return + } + c.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": "验证码发送成功", + }) +} + +// Register +// @Tags 公共方法 +// @Summary 用户注册 +// @Param mail formData string true "mail" +// @Param code formData string true "code" +// @Param name formData string true "name" +// @Param password formData string true "password" +// @Param phone formData string false "phone" +// @Success 200 {string} json "{"code":"200","list":""}" +// @Router /register [post] +func Register(c *gin.Context) { + mail := c.PostForm("mail") + userCode := c.PostForm("code") + name := c.PostForm("name") + password := c.PostForm("password") + phone := c.PostForm("phone") + if mail == "" || userCode == "" || name == "" || password == "" { + c.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": "参数不正确", + }) + return + } + //验证码是否正确 + sysCode, err := models.RDB.Get(c, mail).Result() + if err != nil { + log.Printf("Get Code Error:%v", err) + c.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": "验证码错误,请重新获取验证码", + }) + return + } + if sysCode != userCode { + c.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": "验证码不正确", + }) + return + } + //判断邮箱是否已存在 + var cnt int64 + err = models.DB.Where("mail = ?", mail).Model(new(models.UserBasic)).Count(&cnt).Error + if err != nil { + c.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": "Get User Error" + err.Error(), + }) + return + } + if cnt > 0 { + c.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": "该邮箱已被注册", + }) + return + } + + //数据插入 + userIdentity := helper.GetUUID() + data := &models.UserBasic{ + Identity: userIdentity, + Name: name, + Password: helper.GetMd5(password), + Phone: phone, + Mail: mail, + } + err = models.DB.Create(data).Error + if err != nil { + c.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": "Get User Error:" + err.Error(), + }) + return + } + //生成token + token, err := helper.GenerateToken(userIdentity, name, data.IsAdmin) + if err != nil { + c.JSON(http.StatusOK, gin.H{ + "code": -1, + "msg": "Generate Token Error:" + err.Error(), + }) + return + } + c.JSON(http.StatusOK, gin.H{ + "code": -1, + "data": map[string]interface{}{ + "token": token, + }, + }) +} + +// GetRankList +// @Tags 公共方法 +// @Summary 用户排行榜 +// @Param page query string false "page" +// @Param size query string false "size" +// @Success 200 {string} json "{"code":"200","list":""}" +// @Router /rank_list [get] +func GetRankList(c *gin.Context) { + size, _ := strconv.Atoi(c.DefaultQuery("size", define.DefaultSize)) + page, err := strconv.Atoi(c.DefaultQuery("page", define.DefaultPage)) + if err != nil { + log.Println("Get ProblemList Page strconv Error:", err) + return + } + //page == 1 ===> offset 0 + page = (page - 1) * size + var count int64 + list := make([]*models.UserBasic, 0) + err = models.DB.Model(new(models.UserBasic)).Count(&count).Order("finish_problem_num DESC,submit_num ASC"). + Offset(page).Limit(size).Find(&list).Error + if err != nil { + c.JSON(http.StatusOK, gin.H{ + "code": 200, + "msg": "Get Rank List Error:" + err.Error(), + }) + } + + c.JSON(http.StatusOK, gin.H{ + "code": 200, + "data": map[string]interface{}{ + "list": list, + "count": count, + }, + }) +} diff --git a/test/email_test.go b/test/email_test.go new file mode 100644 index 0000000..8f40667 --- /dev/null +++ b/test/email_test.go @@ -0,0 +1,26 @@ +package test + +import ( + "github.com/jordan-wright/email" + "net/smtp" + "testing" +) + +func TestSendEmail(t *testing.T) { + e := email.NewEmail() + e.From = "Crayon <2993373191@qq.com>" + e.To = []string{"sudolsq@gmail.com"} + e.Subject = "验证发送测试" + + e.HTML = []byte("

Fancy HTML12311231 is supported, too!

") + err := e.Send("smtp.qq.com:587", smtp.PlainAuth("", "2993373191@qq.com", "vlkrwkqjayqedehc", "smtp.qq.com")) + //返回EOF时,关闭SLL重试 + //err := e.SendWithTLS("smtp.qq.com:587", + // smtp.PlainAuth("", "2993373191@qq.com", + // "vlkrwkqjayqedehc", "smtp.qq.com"), + // &tls.Config{InsecureSkipVerify: true, ServerName: "smtp.qq.com"}) + + if err != nil { + t.Fatal(err) + } +} diff --git a/test/gorm_test.go b/test/gorm_test.go new file mode 100644 index 0000000..845fba0 --- /dev/null +++ b/test/gorm_test.go @@ -0,0 +1,25 @@ +package test + +import ( + "fmt" + "gorm.io/driver/mysql" + "gorm.io/gorm" + "lsq.com/models" + "testing" +) + +func TestGormTest(t *testing.T) { + dsn := "root:root@tcp(127.0.0.1:3306)/gin_gorm_oj?charset=utf8mb4&parseTime=True&loc=Local" + db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) + if err != nil { + t.Fatal(err) + } + data := make([]*models.ProblemBasic, 0) + err = db.Find(&data).Error + if err != nil { + t.Fatal(err) + } + for _, v := range data { + fmt.Printf("Problem====>%v\n", v) + } +} diff --git a/test/jwt_test.go b/test/jwt_test.go new file mode 100644 index 0000000..2d0bd28 --- /dev/null +++ b/test/jwt_test.go @@ -0,0 +1,54 @@ +package test + +import ( + "fmt" + "github.com/golang-jwt/jwt/v4" + "testing" + "time" +) + +type UserClaims struct { + Identity string `json:"identity"` + Name string `json:"name"` + jwt.StandardClaims +} + +// TODO 签名密钥 +var myKey = []byte("gin-gorm-oj-key") + +func TestGenerateToken(t *testing.T) { + UserClaims := &UserClaims{ + Identity: "user_1", + Name: "get", + StandardClaims: jwt.StandardClaims{ + NotBefore: time.Now().Unix() - 60, // 令牌在当前时间的前60秒之前不生效 + ExpiresAt: time.Now().Unix() + 5, // 令牌将在当前时间的后5秒过期 + Issuer: "lsq", // 令牌的发行者 + }, + } + //TODO 使用指定的签名方法和声明创建一个新的令牌 + token := jwt.NewWithClaims(jwt.SigningMethodHS256, UserClaims) + //TODO 使用签名密钥对令牌进行签名,并获取完整的签名后的令牌字符串 + tokenString, err := token.SignedString(myKey) + if err != nil { + t.Fatal(err) + return + } + fmt.Println(tokenString) + //eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZGVudGl0eSI6InVzZXJfMSIsIm5hbWUiOiJnZXQifQ.taKAmMZu6-6ioE4hSKqUgn9lHrqXSw-2TyEQTeNOreA +} + +func TestAnalyseToken(t *testing.T) { + tokenString := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZGVudGl0eSI6InVzZXJfMSIsIm5hbWUiOiJnZXQifQ.taKAmMZu6-6ioE4hSKqUgn9lHrqXSw-2TyEQTeNOreA" + userClaim := new(UserClaims) + //TODO 解析 JWT,并在解析的过程中验证签名 + claims, err := jwt.ParseWithClaims(tokenString, userClaim, func(token *jwt.Token) (interface{}, error) { + return myKey, nil + }) + if err != nil { + t.Fatal(err) + } + if claims.Valid { + fmt.Println(userClaim) + } +} diff --git a/test/redis_test.go b/test/redis_test.go new file mode 100644 index 0000000..97f6abd --- /dev/null +++ b/test/redis_test.go @@ -0,0 +1,37 @@ +package test + +import ( + "context" + "fmt" + "github.com/redis/go-redis/v9" + "lsq.com/models" + "testing" + "time" +) + +var ctx = context.Background() +var rdb = redis.NewClient(&redis.Options{ + Addr: "127.0.0.1:6379", + Password: "", // no password set + DB: 0, // use default DB +}) + +func TestRedisSet(t *testing.T) { + rdb.Set(ctx, "name", "mmc", time.Second*10) +} + +func TestRedisGet(t *testing.T) { + v, err := rdb.Get(ctx, "name").Result() + if err != nil { + t.Fatal(err) + } + fmt.Println(v) +} + +func TestRedisGetByModels(t *testing.T) { + v, err := models.RDB.Get(ctx, "name").Result() + if err != nil { + t.Fatal(err) + } + fmt.Println(v) +} diff --git a/test/uuid_test.go b/test/uuid_test.go new file mode 100644 index 0000000..32ec28a --- /dev/null +++ b/test/uuid_test.go @@ -0,0 +1,16 @@ +package test + +import ( + uuid "github.com/satori/go.uuid" + "testing" +) + +func TestGenerateUUID(t *testing.T) { + println(uuid.NewV4().String()) + println(uuid.NewV4().String()) + println(uuid.NewV4().String()) + println(uuid.NewV4().String()) + println(uuid.NewV4().String()) + println(len(uuid.NewV4().String())) + +}