diff --git a/.minio.sys/buckets/.bloomcycle.bin b/.minio.sys/buckets/.bloomcycle.bin new file mode 100644 index 00000000..0117a8bc Binary files /dev/null and b/.minio.sys/buckets/.bloomcycle.bin differ diff --git a/.minio.sys/buckets/.minio.sys/buckets/.usage-cache.bin/fs.json b/.minio.sys/buckets/.minio.sys/buckets/.usage-cache.bin/fs.json new file mode 100644 index 00000000..82931635 --- /dev/null +++ b/.minio.sys/buckets/.minio.sys/buckets/.usage-cache.bin/fs.json @@ -0,0 +1 @@ +{"version":"1.0.2","checksum":{"algorithm":"","blocksize":0,"hashes":null},"meta":{"etag":"24875af2ad02c0be3096aa4475889d38"}} \ No newline at end of file diff --git a/.minio.sys/buckets/.minio.sys/buckets/app/.usage-cache.bin/fs.json b/.minio.sys/buckets/.minio.sys/buckets/app/.usage-cache.bin/fs.json new file mode 100644 index 00000000..251bf2b6 --- /dev/null +++ b/.minio.sys/buckets/.minio.sys/buckets/app/.usage-cache.bin/fs.json @@ -0,0 +1 @@ +{"version":"1.0.2","checksum":{"algorithm":"","blocksize":0,"hashes":null},"meta":{"etag":"a43ee200a9b5b13ca89d536328b55eb0"}} \ No newline at end of file diff --git a/.minio.sys/buckets/.minio.sys/buckets/base/.usage-cache.bin/fs.json b/.minio.sys/buckets/.minio.sys/buckets/base/.usage-cache.bin/fs.json new file mode 100644 index 00000000..25390b8a --- /dev/null +++ b/.minio.sys/buckets/.minio.sys/buckets/base/.usage-cache.bin/fs.json @@ -0,0 +1 @@ +{"version":"1.0.2","checksum":{"algorithm":"","blocksize":0,"hashes":null},"meta":{"etag":"b0f726419ecd7eeb85e584ba57d77b7f"}} \ No newline at end of file diff --git a/.minio.sys/buckets/.minio.sys/buckets/database/.usage-cache.bin/fs.json b/.minio.sys/buckets/.minio.sys/buckets/database/.usage-cache.bin/fs.json new file mode 100644 index 00000000..5fdcf7e6 --- /dev/null +++ b/.minio.sys/buckets/.minio.sys/buckets/database/.usage-cache.bin/fs.json @@ -0,0 +1 @@ +{"version":"1.0.2","checksum":{"algorithm":"","blocksize":0,"hashes":null},"meta":{"etag":"e7546e8e99df0980c20811145ef54c51"}} \ No newline at end of file diff --git a/.minio.sys/buckets/.minio.sys/buckets/docs/.usage-cache.bin/fs.json b/.minio.sys/buckets/.minio.sys/buckets/docs/.usage-cache.bin/fs.json new file mode 100644 index 00000000..51ce1fd9 --- /dev/null +++ b/.minio.sys/buckets/.minio.sys/buckets/docs/.usage-cache.bin/fs.json @@ -0,0 +1 @@ +{"version":"1.0.2","checksum":{"algorithm":"","blocksize":0,"hashes":null},"meta":{"etag":"5111bcbd33222bfbdd82354c36cc0337"}} \ No newline at end of file diff --git a/.minio.sys/buckets/.minio.sys/buckets/event/.usage-cache.bin/fs.json b/.minio.sys/buckets/.minio.sys/buckets/event/.usage-cache.bin/fs.json new file mode 100644 index 00000000..e63977e1 --- /dev/null +++ b/.minio.sys/buckets/.minio.sys/buckets/event/.usage-cache.bin/fs.json @@ -0,0 +1 @@ +{"version":"1.0.2","checksum":{"algorithm":"","blocksize":0,"hashes":null},"meta":{"etag":"4c19a1f21a85db0bc7b89e0fcfe39191"}} \ No newline at end of file diff --git a/.minio.sys/buckets/.minio.sys/buckets/images/.usage-cache.bin/fs.json b/.minio.sys/buckets/.minio.sys/buckets/images/.usage-cache.bin/fs.json new file mode 100644 index 00000000..e2bf8f31 --- /dev/null +++ b/.minio.sys/buckets/.minio.sys/buckets/images/.usage-cache.bin/fs.json @@ -0,0 +1 @@ +{"version":"1.0.2","checksum":{"algorithm":"","blocksize":0,"hashes":null},"meta":{"etag":"eddb3a38ec980fb5bf0afedd7bd482c5"}} \ No newline at end of file diff --git a/.minio.sys/buckets/.minio.sys/buckets/problems/.usage-cache.bin/fs.json b/.minio.sys/buckets/.minio.sys/buckets/problems/.usage-cache.bin/fs.json new file mode 100644 index 00000000..951c3dfa --- /dev/null +++ b/.minio.sys/buckets/.minio.sys/buckets/problems/.usage-cache.bin/fs.json @@ -0,0 +1 @@ +{"version":"1.0.2","checksum":{"algorithm":"","blocksize":0,"hashes":null},"meta":{"etag":"38c1017dea279b7022faa23459828676"}} \ No newline at end of file diff --git a/.minio.sys/buckets/.minio.sys/buckets/scripts/.usage-cache.bin/fs.json b/.minio.sys/buckets/.minio.sys/buckets/scripts/.usage-cache.bin/fs.json new file mode 100644 index 00000000..3bd7da09 --- /dev/null +++ b/.minio.sys/buckets/.minio.sys/buckets/scripts/.usage-cache.bin/fs.json @@ -0,0 +1 @@ +{"version":"1.0.2","checksum":{"algorithm":"","blocksize":0,"hashes":null},"meta":{"etag":"53e9679469590a412cf8ef076841e1dc"}} \ No newline at end of file diff --git a/.minio.sys/buckets/.minio.sys/buckets/submissions/.usage-cache.bin/fs.json b/.minio.sys/buckets/.minio.sys/buckets/submissions/.usage-cache.bin/fs.json new file mode 100644 index 00000000..29afe112 --- /dev/null +++ b/.minio.sys/buckets/.minio.sys/buckets/submissions/.usage-cache.bin/fs.json @@ -0,0 +1 @@ +{"version":"1.0.2","checksum":{"algorithm":"","blocksize":0,"hashes":null},"meta":{"etag":"d74225a715028548a67b160bbcc00244"}} \ No newline at end of file diff --git a/.minio.sys/buckets/.minio.sys/buckets/template/.usage-cache.bin/fs.json b/.minio.sys/buckets/.minio.sys/buckets/template/.usage-cache.bin/fs.json new file mode 100644 index 00000000..84cb5aea --- /dev/null +++ b/.minio.sys/buckets/.minio.sys/buckets/template/.usage-cache.bin/fs.json @@ -0,0 +1 @@ +{"version":"1.0.2","checksum":{"algorithm":"","blocksize":0,"hashes":null},"meta":{"etag":"c52a3c6609fb5daa573eb326389aaae1"}} \ No newline at end of file diff --git a/.minio.sys/buckets/.tracker.bin b/.minio.sys/buckets/.tracker.bin new file mode 100644 index 00000000..5b592afb Binary files /dev/null and b/.minio.sys/buckets/.tracker.bin differ diff --git a/.minio.sys/buckets/.usage-cache.bin b/.minio.sys/buckets/.usage-cache.bin new file mode 100644 index 00000000..c45b0328 Binary files /dev/null and b/.minio.sys/buckets/.usage-cache.bin differ diff --git a/.minio.sys/buckets/.usage.json b/.minio.sys/buckets/.usage.json new file mode 100644 index 00000000..a486b555 --- /dev/null +++ b/.minio.sys/buckets/.usage.json @@ -0,0 +1 @@ +{"lastUpdate":"2022-08-27T21:11:14.1118762+08:00","objectsCount":151,"objectsTotalSize":61095515,"objectsReplicationInfo":null,"bucketsCount":10,"bucketsUsageInfo":{"app":{"size":60755226,"objectsPendingReplicationTotalSize":0,"objectsFailedReplicationTotalSize":0,"objectsReplicatedTotalSize":0,"objectsPendingReplicationCount":0,"objectsFailedReplicationCount":0,"objectsCount":77,"objectsSizesHistogram":{"BETWEEN_1024_B_AND_1_MB":56,"BETWEEN_10_MB_AND_64_MB":1,"BETWEEN_128_MB_AND_512_MB":0,"BETWEEN_1_MB_AND_10_MB":0,"BETWEEN_64_MB_AND_128_MB":0,"GREATER_THAN_512_MB":0,"LESS_THAN_1024_B":20},"objectReplicaTotalSize":0,"objectsReplicationInfo":{}},"base":{"size":129938,"objectsPendingReplicationTotalSize":0,"objectsFailedReplicationTotalSize":0,"objectsReplicatedTotalSize":0,"objectsPendingReplicationCount":0,"objectsFailedReplicationCount":0,"objectsCount":38,"objectsSizesHistogram":{"BETWEEN_1024_B_AND_1_MB":28,"BETWEEN_10_MB_AND_64_MB":0,"BETWEEN_128_MB_AND_512_MB":0,"BETWEEN_1_MB_AND_10_MB":0,"BETWEEN_64_MB_AND_128_MB":0,"GREATER_THAN_512_MB":0,"LESS_THAN_1024_B":10},"objectReplicaTotalSize":0,"objectsReplicationInfo":{}},"database":{"size":104362,"objectsPendingReplicationTotalSize":0,"objectsFailedReplicationTotalSize":0,"objectsReplicatedTotalSize":0,"objectsPendingReplicationCount":0,"objectsFailedReplicationCount":0,"objectsCount":25,"objectsSizesHistogram":{"BETWEEN_1024_B_AND_1_MB":14,"BETWEEN_10_MB_AND_64_MB":0,"BETWEEN_128_MB_AND_512_MB":0,"BETWEEN_1_MB_AND_10_MB":0,"BETWEEN_64_MB_AND_128_MB":0,"GREATER_THAN_512_MB":0,"LESS_THAN_1024_B":11},"objectReplicaTotalSize":0,"objectsReplicationInfo":{}},"docs":{"size":93002,"objectsPendingReplicationTotalSize":0,"objectsFailedReplicationTotalSize":0,"objectsReplicatedTotalSize":0,"objectsPendingReplicationCount":0,"objectsFailedReplicationCount":0,"objectsCount":3,"objectsSizesHistogram":{"BETWEEN_1024_B_AND_1_MB":3,"BETWEEN_10_MB_AND_64_MB":0,"BETWEEN_128_MB_AND_512_MB":0,"BETWEEN_1_MB_AND_10_MB":0,"BETWEEN_64_MB_AND_128_MB":0,"GREATER_THAN_512_MB":0,"LESS_THAN_1024_B":0},"objectReplicaTotalSize":0,"objectsReplicationInfo":{}},"event":{"size":2852,"objectsPendingReplicationTotalSize":0,"objectsFailedReplicationTotalSize":0,"objectsReplicatedTotalSize":0,"objectsPendingReplicationCount":0,"objectsFailedReplicationCount":0,"objectsCount":7,"objectsSizesHistogram":{"BETWEEN_1024_B_AND_1_MB":1,"BETWEEN_10_MB_AND_64_MB":0,"BETWEEN_128_MB_AND_512_MB":0,"BETWEEN_1_MB_AND_10_MB":0,"BETWEEN_64_MB_AND_128_MB":0,"GREATER_THAN_512_MB":0,"LESS_THAN_1024_B":6},"objectReplicaTotalSize":0,"objectsReplicationInfo":{}},"images":{"size":0,"objectsPendingReplicationTotalSize":0,"objectsFailedReplicationTotalSize":0,"objectsReplicatedTotalSize":0,"objectsPendingReplicationCount":0,"objectsFailedReplicationCount":0,"objectsCount":0,"objectsSizesHistogram":{"BETWEEN_1024_B_AND_1_MB":0,"BETWEEN_10_MB_AND_64_MB":0,"BETWEEN_128_MB_AND_512_MB":0,"BETWEEN_1_MB_AND_10_MB":0,"BETWEEN_64_MB_AND_128_MB":0,"GREATER_THAN_512_MB":0,"LESS_THAN_1024_B":0},"objectReplicaTotalSize":0,"objectsReplicationInfo":null},"problems":{"size":0,"objectsPendingReplicationTotalSize":0,"objectsFailedReplicationTotalSize":0,"objectsReplicatedTotalSize":0,"objectsPendingReplicationCount":0,"objectsFailedReplicationCount":0,"objectsCount":0,"objectsSizesHistogram":{"BETWEEN_1024_B_AND_1_MB":0,"BETWEEN_10_MB_AND_64_MB":0,"BETWEEN_128_MB_AND_512_MB":0,"BETWEEN_1_MB_AND_10_MB":0,"BETWEEN_64_MB_AND_128_MB":0,"GREATER_THAN_512_MB":0,"LESS_THAN_1024_B":0},"objectReplicaTotalSize":0,"objectsReplicationInfo":null},"scripts":{"size":0,"objectsPendingReplicationTotalSize":0,"objectsFailedReplicationTotalSize":0,"objectsReplicatedTotalSize":0,"objectsPendingReplicationCount":0,"objectsFailedReplicationCount":0,"objectsCount":0,"objectsSizesHistogram":{"BETWEEN_1024_B_AND_1_MB":0,"BETWEEN_10_MB_AND_64_MB":0,"BETWEEN_128_MB_AND_512_MB":0,"BETWEEN_1_MB_AND_10_MB":0,"BETWEEN_64_MB_AND_128_MB":0,"GREATER_THAN_512_MB":0,"LESS_THAN_1024_B":0},"objectReplicaTotalSize":0,"objectsReplicationInfo":null},"submissions":{"size":0,"objectsPendingReplicationTotalSize":0,"objectsFailedReplicationTotalSize":0,"objectsReplicatedTotalSize":0,"objectsPendingReplicationCount":0,"objectsFailedReplicationCount":0,"objectsCount":0,"objectsSizesHistogram":{"BETWEEN_1024_B_AND_1_MB":0,"BETWEEN_10_MB_AND_64_MB":0,"BETWEEN_128_MB_AND_512_MB":0,"BETWEEN_1_MB_AND_10_MB":0,"BETWEEN_64_MB_AND_128_MB":0,"GREATER_THAN_512_MB":0,"LESS_THAN_1024_B":0},"objectReplicaTotalSize":0,"objectsReplicationInfo":null},"template":{"size":10135,"objectsPendingReplicationTotalSize":0,"objectsFailedReplicationTotalSize":0,"objectsReplicatedTotalSize":0,"objectsPendingReplicationCount":0,"objectsFailedReplicationCount":0,"objectsCount":1,"objectsSizesHistogram":{"BETWEEN_1024_B_AND_1_MB":1,"BETWEEN_10_MB_AND_64_MB":0,"BETWEEN_128_MB_AND_512_MB":0,"BETWEEN_1_MB_AND_10_MB":0,"BETWEEN_64_MB_AND_128_MB":0,"GREATER_THAN_512_MB":0,"LESS_THAN_1024_B":0},"objectReplicaTotalSize":0,"objectsReplicationInfo":{}}},"bucketsSizes":null} \ No newline at end of file diff --git a/.minio.sys/buckets/app/.usage-cache.bin b/.minio.sys/buckets/app/.usage-cache.bin new file mode 100644 index 00000000..a5e893ae Binary files /dev/null and b/.minio.sys/buckets/app/.usage-cache.bin differ diff --git a/.minio.sys/buckets/base/.usage-cache.bin b/.minio.sys/buckets/base/.usage-cache.bin new file mode 100644 index 00000000..6f3001c4 Binary files /dev/null and b/.minio.sys/buckets/base/.usage-cache.bin differ diff --git a/.minio.sys/buckets/database/.usage-cache.bin b/.minio.sys/buckets/database/.usage-cache.bin new file mode 100644 index 00000000..f28cb54e Binary files /dev/null and b/.minio.sys/buckets/database/.usage-cache.bin differ diff --git a/.minio.sys/buckets/docs/.usage-cache.bin b/.minio.sys/buckets/docs/.usage-cache.bin new file mode 100644 index 00000000..5877e28f Binary files /dev/null and b/.minio.sys/buckets/docs/.usage-cache.bin differ diff --git a/.minio.sys/buckets/event/.usage-cache.bin b/.minio.sys/buckets/event/.usage-cache.bin new file mode 100644 index 00000000..984313e7 Binary files /dev/null and b/.minio.sys/buckets/event/.usage-cache.bin differ diff --git a/.minio.sys/buckets/images/.metadata.bin b/.minio.sys/buckets/images/.metadata.bin new file mode 100644 index 00000000..520efeec Binary files /dev/null and b/.minio.sys/buckets/images/.metadata.bin differ diff --git a/.minio.sys/buckets/images/.usage-cache.bin b/.minio.sys/buckets/images/.usage-cache.bin new file mode 100644 index 00000000..e42e130b Binary files /dev/null and b/.minio.sys/buckets/images/.usage-cache.bin differ diff --git a/.minio.sys/buckets/problems/.metadata.bin b/.minio.sys/buckets/problems/.metadata.bin new file mode 100644 index 00000000..4f496f16 Binary files /dev/null and b/.minio.sys/buckets/problems/.metadata.bin differ diff --git a/.minio.sys/buckets/problems/.usage-cache.bin b/.minio.sys/buckets/problems/.usage-cache.bin new file mode 100644 index 00000000..ff508d94 Binary files /dev/null and b/.minio.sys/buckets/problems/.usage-cache.bin differ diff --git a/.minio.sys/buckets/scripts/.metadata.bin b/.minio.sys/buckets/scripts/.metadata.bin new file mode 100644 index 00000000..9da81ff0 Binary files /dev/null and b/.minio.sys/buckets/scripts/.metadata.bin differ diff --git a/.minio.sys/buckets/scripts/.usage-cache.bin b/.minio.sys/buckets/scripts/.usage-cache.bin new file mode 100644 index 00000000..7b9e3387 Binary files /dev/null and b/.minio.sys/buckets/scripts/.usage-cache.bin differ diff --git a/.minio.sys/buckets/submissions/.metadata.bin b/.minio.sys/buckets/submissions/.metadata.bin new file mode 100644 index 00000000..1ae8be98 Binary files /dev/null and b/.minio.sys/buckets/submissions/.metadata.bin differ diff --git a/.minio.sys/buckets/submissions/.usage-cache.bin b/.minio.sys/buckets/submissions/.usage-cache.bin new file mode 100644 index 00000000..8f7c0525 Binary files /dev/null and b/.minio.sys/buckets/submissions/.usage-cache.bin differ diff --git a/.minio.sys/buckets/template/.usage-cache.bin b/.minio.sys/buckets/template/.usage-cache.bin new file mode 100644 index 00000000..d02b1105 Binary files /dev/null and b/.minio.sys/buckets/template/.usage-cache.bin differ diff --git a/.minio.sys/config/config.json b/.minio.sys/config/config.json new file mode 100644 index 00000000..ae37fbb4 --- /dev/null +++ b/.minio.sys/config/config.json @@ -0,0 +1 @@ +{"api":{"_":[{"key":"requests_max","value":"0"},{"key":"requests_deadline","value":"10s"},{"key":"cluster_deadline","value":"10s"},{"key":"cors_allow_origin","value":"*"},{"key":"remote_transport_deadline","value":"2h"},{"key":"list_quorum","value":"strict"},{"key":"replication_workers","value":"250"},{"key":"replication_failed_workers","value":"8"},{"key":"transition_workers","value":"100"},{"key":"stale_uploads_cleanup_interval","value":"6h"},{"key":"stale_uploads_expiry","value":"24h"},{"key":"delete_cleanup_interval","value":"5m"},{"key":"disable_odirect","value":"off"}]},"audit_kafka":{"_":[{"key":"enable","value":"off"},{"key":"topic","value":""},{"key":"brokers","value":""},{"key":"sasl_username","value":""},{"key":"sasl_password","value":""},{"key":"sasl_mechanism","value":"plain"},{"key":"client_tls_cert","value":""},{"key":"client_tls_key","value":""},{"key":"tls_client_auth","value":"0"},{"key":"sasl","value":"off"},{"key":"tls","value":"off"},{"key":"tls_skip_verify","value":"off"},{"key":"version","value":""}]},"audit_webhook":{"_":[{"key":"enable","value":"off"},{"key":"endpoint","value":""},{"key":"auth_token","value":""},{"key":"client_cert","value":""},{"key":"client_key","value":""},{"key":"queue_size","value":"100000"}]},"cache":{"_":[{"key":"drives","value":""},{"key":"exclude","value":""},{"key":"expiry","value":"90"},{"key":"quota","value":"80"},{"key":"after","value":"0"},{"key":"watermark_low","value":"70"},{"key":"watermark_high","value":"80"},{"key":"range","value":"on"},{"key":"commit","value":""}]},"compression":{"_":[{"key":"enable","value":"off"},{"key":"allow_encryption","value":"off"},{"key":"extensions","value":".txt,.log,.csv,.json,.tar,.xml,.bin"},{"key":"mime_types","value":"text/*,application/json,application/xml,binary/octet-stream"}]},"credentials":{"_":[{"key":"access_key","value":"minioadmin"},{"key":"secret_key","value":"minioadmin"}]},"etcd":{"_":[{"key":"endpoints","value":""},{"key":"path_prefix","value":""},{"key":"coredns_path","value":"/skydns"},{"key":"client_cert","value":""},{"key":"client_cert_key","value":""}]},"heal":{"_":[{"key":"bitrotscan","value":"off"},{"key":"max_sleep","value":"1s"},{"key":"max_io","value":"100"}]},"identity_ldap":{"_":[{"key":"server_addr","value":""},{"key":"user_dn_search_base_dn","value":""},{"key":"user_dn_search_filter","value":""},{"key":"group_search_filter","value":""},{"key":"group_search_base_dn","value":""},{"key":"tls_skip_verify","value":"off"},{"key":"server_insecure","value":"off"},{"key":"server_starttls","value":"off"},{"key":"lookup_bind_dn","value":""},{"key":"lookup_bind_password","value":""}]},"identity_openid":{"_":[{"key":"config_url","value":""},{"key":"client_id","value":""},{"key":"client_secret","value":""},{"key":"claim_name","value":"policy"},{"key":"claim_userinfo","value":""},{"key":"role_policy","value":""},{"key":"claim_prefix","value":""},{"key":"redirect_uri","value":""},{"key":"redirect_uri_dynamic","value":"off"},{"key":"scopes","value":""}]},"identity_tls":{"_":[{"key":"skip_verify","value":"off"}]},"logger_webhook":{"_":[{"key":"enable","value":"off"},{"key":"endpoint","value":""},{"key":"auth_token","value":""},{"key":"client_cert","value":""},{"key":"client_key","value":""},{"key":"queue_size","value":"100000"}]},"notify_amqp":{"_":[{"key":"enable","value":"off"},{"key":"url","value":""},{"key":"exchange","value":""},{"key":"exchange_type","value":""},{"key":"routing_key","value":""},{"key":"mandatory","value":"off"},{"key":"durable","value":"off"},{"key":"no_wait","value":"off"},{"key":"internal","value":"off"},{"key":"auto_deleted","value":"off"},{"key":"delivery_mode","value":"0"},{"key":"publisher_confirms","value":"off"},{"key":"queue_limit","value":"0"},{"key":"queue_dir","value":""}]},"notify_elasticsearch":{"_":[{"key":"enable","value":"off"},{"key":"url","value":""},{"key":"format","value":"namespace"},{"key":"index","value":""},{"key":"queue_dir","value":""},{"key":"queue_limit","value":"0"},{"key":"username","value":""},{"key":"password","value":""}]},"notify_kafka":{"_":[{"key":"enable","value":"off"},{"key":"topic","value":""},{"key":"brokers","value":""},{"key":"sasl_username","value":""},{"key":"sasl_password","value":""},{"key":"sasl_mechanism","value":"plain"},{"key":"client_tls_cert","value":""},{"key":"client_tls_key","value":""},{"key":"tls_client_auth","value":"0"},{"key":"sasl","value":"off"},{"key":"tls","value":"off"},{"key":"tls_skip_verify","value":"off"},{"key":"queue_limit","value":"0"},{"key":"queue_dir","value":""},{"key":"version","value":""}]},"notify_mqtt":{"_":[{"key":"enable","value":"off"},{"key":"broker","value":""},{"key":"topic","value":""},{"key":"password","value":""},{"key":"username","value":""},{"key":"qos","value":"0"},{"key":"keep_alive_interval","value":"0s"},{"key":"reconnect_interval","value":"0s"},{"key":"queue_dir","value":""},{"key":"queue_limit","value":"0"}]},"notify_mysql":{"_":[{"key":"enable","value":"off"},{"key":"format","value":"namespace"},{"key":"dsn_string","value":""},{"key":"table","value":""},{"key":"queue_dir","value":""},{"key":"queue_limit","value":"0"},{"key":"max_open_connections","value":"2"}]},"notify_nats":{"_":[{"key":"enable","value":"off"},{"key":"address","value":""},{"key":"subject","value":""},{"key":"username","value":""},{"key":"password","value":""},{"key":"token","value":""},{"key":"tls","value":"off"},{"key":"tls_skip_verify","value":"off"},{"key":"cert_authority","value":""},{"key":"client_cert","value":""},{"key":"client_key","value":""},{"key":"ping_interval","value":"0"},{"key":"streaming","value":"off"},{"key":"streaming_async","value":"off"},{"key":"streaming_max_pub_acks_in_flight","value":"0"},{"key":"streaming_cluster_id","value":""},{"key":"queue_dir","value":""},{"key":"queue_limit","value":"0"}]},"notify_nsq":{"_":[{"key":"enable","value":"off"},{"key":"nsqd_address","value":""},{"key":"topic","value":""},{"key":"tls","value":"off"},{"key":"tls_skip_verify","value":"off"},{"key":"queue_dir","value":""},{"key":"queue_limit","value":"0"}]},"notify_postgres":{"_":[{"key":"enable","value":"off"},{"key":"format","value":"namespace"},{"key":"connection_string","value":""},{"key":"table","value":""},{"key":"queue_dir","value":""},{"key":"queue_limit","value":"0"},{"key":"max_open_connections","value":"2"}]},"notify_redis":{"_":[{"key":"enable","value":"off"},{"key":"format","value":"namespace"},{"key":"address","value":""},{"key":"key","value":""},{"key":"password","value":""},{"key":"queue_dir","value":""},{"key":"queue_limit","value":"0"}]},"notify_webhook":{"_":[{"key":"enable","value":"off"},{"key":"endpoint","value":""},{"key":"auth_token","value":""},{"key":"queue_limit","value":"0"},{"key":"queue_dir","value":""},{"key":"client_cert","value":""},{"key":"client_key","value":""}]},"policy_opa":{"_":[{"key":"url","value":""},{"key":"auth_token","value":""}]},"region":{"_":[{"key":"name","value":""}]},"scanner":{"_":[{"key":"delay","value":"10"},{"key":"max_wait","value":"15s"},{"key":"cycle","value":"1m"}]},"site":{"_":[{"key":"name","value":""},{"key":"region","value":""}]},"storage_class":{"_":null},"subnet":{"_":[{"key":"license","value":""},{"key":"api_key","value":""}]}} \ No newline at end of file diff --git a/.minio.sys/config/iam/format.json b/.minio.sys/config/iam/format.json new file mode 100644 index 00000000..491d7344 --- /dev/null +++ b/.minio.sys/config/iam/format.json @@ -0,0 +1 @@ +{"version":1} \ No newline at end of file diff --git a/.minio.sys/format.json b/.minio.sys/format.json new file mode 100644 index 00000000..b5fcb836 --- /dev/null +++ b/.minio.sys/format.json @@ -0,0 +1 @@ +{"version":"1","format":"fs","id":"6d992242-ba81-472d-bca5-0e3b5e7f298e","fs":{"version":"2"}} \ No newline at end of file diff --git a/app/controller/solution.go b/app/controller/solution.go new file mode 100644 index 00000000..a079fd88 --- /dev/null +++ b/app/controller/solution.go @@ -0,0 +1,140 @@ +package controller + +import ( + "fmt" + "net/http" + "strconv" + "strings" + + "github.com/EduOJ/backend/app/request" + "github.com/EduOJ/backend/app/response" + "github.com/EduOJ/backend/app/response/resource" + "github.com/EduOJ/backend/base" + "github.com/EduOJ/backend/base/utils" + "github.com/EduOJ/backend/database/models" + "github.com/labstack/echo/v4" + "github.com/pkg/errors" + "gorm.io/gorm" +) + +func GetSolutions(c echo.Context) error { + req := request.GetSolutionsRequest{} + if err, ok := utils.BindAndValidate(&req, c); !ok { + return err + } + + problemID, _ := strconv.ParseUint(req.ProblemID, 10, 64) + query := base.DB.Model(&models.Solution{}).Order("problem_id ASC").Where("problem_id = ?", problemID) + var solutions []*models.Solution + + err := query.Find(&solutions).Error + if err != nil { + if herr, ok := err.(utils.HttpError); ok { + return herr.Response(c) + } + panic(err) + } + + return c.JSON(http.StatusOK, response.GetSolutionsResponse{ + Message: "SUCCESS", + Error: nil, + Data: struct { + Solutions []resource.Solution `json:"solutions"` + }{ + Solutions: resource.GetSolutions(solutions), + }, + }) +} + +func CreateSolution(c echo.Context) error { + req := request.CreateSolutionRequest{} + err, ok := utils.BindAndValidate(&req, c) + if !ok { + return err + } + + solution := models.Solution{ + ProblemID: req.ProblemID, + Name: req.Name, + Author: req.Author, + Description: req.Description, + Likes: "", + } + utils.PanicIfDBError(base.DB.Create(&solution), "could not create solution") + + return c.JSON(http.StatusCreated, response.CreateSolutionResponse{ + Message: "SUCCESS", + Error: nil, + Data: struct { + *resource.Solution `json:"solution"` + }{ + resource.GetSolution(&solution), + }, + }) +} + +func GetLikes(c echo.Context) error { + req := request.LikesRequest{} + err, ok := utils.BindAndValidate(&req, c) + if !ok { + return err + } + solution := models.Solution{} + query := base.DB.Model(&models.Solution{}) + err = query.Where("id = ?", req.SolutionId).Find(&solution).Error + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return c.JSON(http.StatusNotFound, response.ErrorResp("NOT_FOUND", nil)) + } else { + panic(errors.Wrap(err, "could not query solution")) + } + } + // err = query.Where("id = ?", req.SolutionId).Update("likes", "").Error + // fmt.Println(solution.Likes) + // "1,2,3,4" + likeList := strings.Split(solution.Likes, ",") + // likeList := strings.Split("2,3,4,", ",") + // fmt.Println(likeList) + count := len(likeList) - 1 + isLike := false + // fmt.Println(count) + switch req.IsLike { + case 1: + newLikes := solution.Likes + fmt.Sprint(req.UserId) + "," + query.Where("id = ?", req.SolutionId).Update("likes", newLikes) + count = count + 1 + isLike = true + // fmt.Println(newLikes) + case -1: + newLikes := strings.Replace(solution.Likes, fmt.Sprint(req.UserId)+",", "", -1) + query.Where("id = ?", req.SolutionId).Update("likes", newLikes) + count = count - 1 + isLike = false + // fmt.Println(newLikes) + + default: + for i := 0; i < count; i++ { + // fmt.Print(i) + // fmt.Print(": ") + // fmt.Println(likeList[i]) + if fmt.Sprint(req.UserId) == likeList[i] { + isLike = true + } + } + } + + likes := &models.Likes{ + Count: count, + IsLike: isLike, + } + + return c.JSON(http.StatusOK, response.GetLikesResponse{ + Message: "SUCCESS", + Error: nil, + Data: struct { + Likes resource.Likes `json:"likes"` + }{ + Likes: *resource.GetLikes(likes), + }, + }) +} diff --git a/app/controller/soulution_comment.go b/app/controller/soulution_comment.go new file mode 100644 index 00000000..ccea53ff --- /dev/null +++ b/app/controller/soulution_comment.go @@ -0,0 +1,104 @@ +package controller + +import ( + "net/http" + "strconv" + + "github.com/EduOJ/backend/app/request" + "github.com/EduOJ/backend/app/response" + "github.com/EduOJ/backend/app/response/resource" + "github.com/EduOJ/backend/base" + "github.com/EduOJ/backend/base/utils" + "github.com/EduOJ/backend/database/models" + "github.com/labstack/echo/v4" + "github.com/pkg/errors" + "gorm.io/gorm" +) + +func GetSolutionComments(c echo.Context) error { + sc := []models.SolutionComment{} + query := base.DB + err := query.Where("solution_id = ?", c.Param("solutionId")).Find(&sc).Error + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return c.JSON(http.StatusNotFound, response.ErrorResp("NOT_FOUND", nil)) + } else { + panic(errors.Wrap(err, "could not query solution comment")) + } + } + + return c.JSON(http.StatusOK, response.GetSolutionCommentsResponse{ + Message: "SUCCESS", + Error: nil, + Data: struct { + SolutionComments []resource.SolutionComment `json:"solution_comments"` + }{ + resource.GetSolutionComments(sc), + }, + }) +} + +func CreateSolutionComment(c echo.Context) error { + req := request.CreateSolutionCommentRequest{} + err, ok := utils.BindAndValidate(&req, c) + if !ok { + return err + } + var FatherNode uint + if req.IsRoot { + FatherNode = 0 + } else { + FatherNode = req.FatherNode + } + comment := models.SolutionComment{ + SolutionID: req.SolutionID, + FatherNode: FatherNode, + Description: req.Description, + Speaker: req.Speaker, + } + utils.PanicIfDBError(base.DB.Create(&comment), "could not create comment") + return c.JSON(http.StatusOK, response.CreateSolutionCommentResponse{ + Message: "SUCCESS", + Error: nil, + Data: struct { + *resource.SolutionComment `json:"solution_comment_create"` + }{ + resource.GetSolutionComment(&comment), + }, + }) +} + +func GetCommentTree(c echo.Context) error { + req := request.GetSolutionCommentsTreeRequest{} + if err, ok := utils.BindAndValidate(&req, c); !ok { + return err + } + + solutionID, _ := strconv.ParseUint(req.SolutionID, 10, 64) + + solutionComments := []models.SolutionComment{} + query := base.DB.Model(&models.SolutionComment{}) + err := query.Where("solution_id = ?", solutionID).Find(&solutionComments).Error + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return c.JSON(http.StatusNotFound, response.ErrorResp("NOT_FOUND", nil)) + } else { + panic(errors.Wrap(err, "could not query solution comment")) + } + } + + commentNodes := make([]resource.SolutionCommentNode, len(solutionComments)) + for i, solutionComment := range solutionComments { + commentNodes[i].ConvertCommentToNode(&solutionComment) + } + + return c.JSON(http.StatusOK, response.GetCommentTreeResponse{ + Message: "SUCCESS", + Error: nil, + Data: struct { + *resource.SolutionCommentTree `json:"solution_comment_tree"` + }{ + resource.GetSolutionCommentTree(commentNodes), + }, + }) +} diff --git a/app/request/solution.go b/app/request/solution.go new file mode 100644 index 00000000..12178121 --- /dev/null +++ b/app/request/solution.go @@ -0,0 +1,36 @@ +package request + +type CreateSolutionRequest struct { + ProblemID uint `json:"problemID" form:"problemID" query:"problemID" validate:"required"` + Name string `json:"name" form:"name" query:"name" validate:"required,max=255"` + Author string `json:"author" form:"author" query:"author" validate:"required"` + Description string `json:"description" form:"description" query:"description" validate:"required"` +} + +type GetSolutionsRequest struct { + ProblemID string `json:"problemID" form:"problemID" query:"problemID" validate:"required"` +} + +type UpdateSolutionRequest struct { + ProblemID uint `json:"problemID" form:"problemID" query:"problemID" validate:"required"` + Name string `json:"name" form:"name" query:"name" validate:"required,max=255"` + Author string `json:"author" form:"author" query:"author" validate:"required"` + Description string `json:"description" form:"description" query:"description" validate:"required"` + Likes string `json:"likes" form:"likes" query:"likes" validate:"required"` +} + +type LikesRequest struct { + SolutionId uint `json:"solutionId" form:"solutionId" query:"solutionId" validate:"required"` + UserId uint `json:"userId" form:"userId" query:"userId" validate:"required"` + IsLike int `json:"isLike" form:"isLike" query:"isLike"` +} + +// type GetSolutionsRequest struct { +// Search string `json:"search" form:"search" query:"search"` +// UserID uint `json:"user_id" form:"user_id" query:"user_id" validate:"min=0,required_with=Tried Passed"` + +// Limit int `json:"limit" form:"limit" query:"limit" validate:"max=100,min=0"` +// Offset int `json:"offset" form:"offset" query:"offset" validate:"min=0"` + +// Tags string `json:"tags" form:"tags" query:"tags"` +// } diff --git a/app/request/solution_comment.go b/app/request/solution_comment.go new file mode 100644 index 00000000..47738cd0 --- /dev/null +++ b/app/request/solution_comment.go @@ -0,0 +1,20 @@ +package request + +type CreateSolutionCommentRequest struct { + SolutionID uint `json:"solutionId" form:"solutionId" query:"solutionId" validate:"required"` + FatherNode uint `json:"fatherNode" form:"fatherNode" query:"fatherNode" validate:"required"` + Description string `json:"reply" form:"reply" query:"reply" validate:"required"` + Speaker string `json:"speaker" form:"speaker" query:"speaker" validate:"required"` + IsRoot bool `json:"isRoot" form:"isRoot" query:"isRoot"` +} + +type GetSolutionCommentsTreeRequest struct { + SolutionID string `json:"solutionID" form:"solutionID" query:"solutionID" validate:"required"` +} + +type UpdateSolutionCommentRequest struct { + SolutionID uint `json:"solutionId" form:"solutionId" query:"solutionId" validate:"required"` + FatherNode uint `json:"fatherNode" form:"fatherNode" query:"fatherNode" validate:"required"` + Description string `json:"reply" form:"reply" query:"reply" validate:"required"` + Speaker string `json:"speaker" form:"speaker" query:"speaker" validate:"required"` +} diff --git a/app/response/resource/solution.go b/app/response/resource/solution.go new file mode 100644 index 00000000..2f4237bb --- /dev/null +++ b/app/response/resource/solution.go @@ -0,0 +1,55 @@ +package resource + +import ( + "github.com/EduOJ/backend/database/models" +) + +type Solution struct { + ID uint `json:"id"` + + ProblemID uint `json:"problem_id"` + Name string `sql:"index" json:"name"` + Author string `json:"author"` + Description string `json:"description"` + Likes string `json:"likes"` +} + +type Likes struct { + Count int `json:"count"` + IsLike bool `json:"isLike"` +} + +func (s *Solution) convert(solution *models.Solution) { + s.ID = solution.ID + + s.ProblemID = solution.ProblemID + s.Name = solution.Name + s.Author = solution.Author + s.Description = solution.Description + s.Likes = solution.Likes +} + +func (l *Likes) convert(likes *models.Likes) { + l.Count = likes.Count + l.IsLike = likes.IsLike +} + +func GetSolution(solution *models.Solution) *Solution { + s := Solution{} + s.convert(solution) + return &s +} + +func GetSolutions(solutions []*models.Solution) (profiles []Solution) { + profiles = make([]Solution, len(solutions)) + for i, solution := range solutions { + profiles[i].convert(solution) + } + return +} + +func GetLikes(likes *models.Likes) *Likes { + l := Likes{} + l.convert(likes) + return &l +} diff --git a/app/response/resource/solution_comment.go b/app/response/resource/solution_comment.go new file mode 100644 index 00000000..12c2c6a8 --- /dev/null +++ b/app/response/resource/solution_comment.go @@ -0,0 +1,83 @@ +package resource + +import "github.com/EduOJ/backend/database/models" + +type SolutionComment struct { + ID uint `gorm:"primaryKey" json:"id"` + + SolutionID uint `sql:"index" json:"solution_id" gorm:"not null"` + FatherNode uint `json:"father_node" gorm:"not null"` + Description string `json:"description"` + Speaker string `json:"speaker"` +} + +func (sc *SolutionComment) convert(solutionComment *models.SolutionComment) { + sc.ID = solutionComment.ID + + sc.SolutionID = solutionComment.SolutionID + sc.FatherNode = solutionComment.FatherNode + sc.Description = solutionComment.Description + sc.Speaker = solutionComment.Speaker +} + +func GetSolutionComment(solutionComment *models.SolutionComment) *SolutionComment { + sc := SolutionComment{} + sc.convert(solutionComment) + return &sc +} + +func GetSolutionComments(solutionComments []models.SolutionComment) []SolutionComment { + scs := make([]SolutionComment, 0) + for _, sc := range solutionComments { + scs = append(scs, *GetSolutionComment(&sc)) + } + return scs +} + +type SolutionCommentNode struct { + ID uint `gorm:"primaryKey" json:"id"` + + SolutionID uint `sql:"index" json:"solution_id" gorm:"not null"` + FatherNode uint `json:"father_node" gorm:"not null"` + Description string `json:"description"` + Speaker string `json:"speaker"` + + Kids []SolutionCommentNode `json:"kids"` +} + +func (cn *SolutionCommentNode) ConvertCommentToNode(solutionComment *models.SolutionComment) { + cn.ID = solutionComment.ID + cn.SolutionID = solutionComment.SolutionID + cn.FatherNode = solutionComment.FatherNode + cn.Description = solutionComment.Description + cn.Speaker = solutionComment.Speaker + cn.Kids = make([]SolutionCommentNode, 0) +} + +func (commentNode *SolutionCommentNode) GetKids(commentNodes []SolutionCommentNode) { + for _, cn := range commentNodes { + if cn.FatherNode == commentNode.ID { + cn.GetKids(commentNodes) + commentNode.Kids = append(commentNode.Kids, cn) + } + } +} + +type SolutionCommentTree struct { + Roots []SolutionCommentNode `json:"roots"` +} + +func (t *SolutionCommentTree) BuildTree(commentNodes []SolutionCommentNode) { + for _, commentNode := range commentNodes { + if commentNode.FatherNode == 0 { + commentNode.GetKids(commentNodes) + t.Roots = append(t.Roots, commentNode) + } + } +} + +func GetSolutionCommentTree(commentNodes []SolutionCommentNode) *SolutionCommentTree { + sct := SolutionCommentTree{} + sct.BuildTree(commentNodes) + return &sct +} diff --git a/app/response/solution.go b/app/response/solution.go new file mode 100644 index 00000000..4da88d55 --- /dev/null +++ b/app/response/solution.go @@ -0,0 +1,29 @@ +package response + +import ( + "github.com/EduOJ/backend/app/response/resource" +) + +type CreateSolutionResponse struct { + Message string `json:"message"` + Error interface{} `json:"error"` + Data struct { + *resource.Solution `json:"solution"` + } `json:"data"` +} + +type GetSolutionsResponse struct { + Message string `json:"message"` + Error interface{} `json:"error"` + Data struct { + Solutions []resource.Solution `json:"solutions"` + } `json:"data"` +} + +type GetLikesResponse struct { + Message string `json:"message"` + Error interface{} `json:"error"` + Data struct { + Likes resource.Likes `json:"likes"` + } `json:"data"` +} diff --git a/app/response/solution_comment.go b/app/response/solution_comment.go new file mode 100644 index 00000000..3032b263 --- /dev/null +++ b/app/response/solution_comment.go @@ -0,0 +1,43 @@ +package response + +import "github.com/EduOJ/backend/app/response/resource" + +type GetSolutionCommentResponse struct { + Message string `json:"message"` + Error interface{} `json:"error"` + Data struct { + *resource.SolutionComment `json:"solution_comment"` + } `json:"data"` +} + +type CreateSolutionCommentResponse struct { + Message string `json:"message"` + Error interface{} `json:"error"` + Data struct { + *resource.SolutionComment `json:"solution_comment_create"` + } `json:"data"` +} + +type UpdateSolutionCommentResponse struct { + Message string `json:"message"` + Error interface{} `json:"error"` + Data struct { + *resource.SolutionComment `json:"solution_comment"` + } `json:"data"` +} + +type GetSolutionCommentsResponse struct { + Message string `json:"message"` + Error interface{} `json:"error"` + Data struct { + SolutionComments []resource.SolutionComment `json:"solution_comments"` + } `json:"data"` +} + +type GetCommentTreeResponse struct { + Message string `json:"message"` + Error interface{} `json:"error"` + Data struct { + *resource.SolutionCommentTree `json:"solution_comment_tree"` + } `json:"data"` +} diff --git a/app/routes.go b/app/routes.go index 65d6ecd5..0f0791af 100644 --- a/app/routes.go +++ b/app/routes.go @@ -167,6 +167,31 @@ func Register(e *echo.Echo) { submission.GET("/submission/:submission_id/run/:id/compiler_output", controller.GetRunCompilerOutput, middleware.Logged).Name = "submission.getRunCompilerOutput" submission.GET("/submission/:submission_id/run/:id/comparer_output", controller.GetRunComparerOutput, middleware.Logged).Name = "submission.getRunComparerOutput" + // solution APIs + solution := api.Group("", + middleware.ValidateParams(map[string]string{ + "id": "NOT_FOUND", + }), + middleware.Logged, middleware.EmailVerified) + api.POST("/solution", controller.CreateSolution, + middleware.Logged, middleware.EmailVerified, + middleware.HasPermission(middleware.UnscopedPermission{P: "create_solution"}), + ).Name = "solution.createSolution" + solution.GET("/solutions", controller.GetSolutions).Name = "solution.getSolutions" + solution.GET("/likes", controller.GetLikes).Name = "solution.likes" + + // solution comments APIs + solution_comments := api.Group("", + middleware.ValidateParams(map[string]string{ + "id": "NOT_FOUND", + }), + middleware.Logged, middleware.EmailVerified) + api.POST("/solution/comment", controller.CreateSolutionComment, + middleware.Logged, middleware.EmailVerified, + middleware.HasPermission(middleware.UnscopedPermission{P: "create_solution_comment"}), + ).Name = "solution.createSolutionComment" + solution_comments.GET("/solution/comments", controller.GetCommentTree).Name = "solution.getSolutionComments" + // log API api.GET("/admin/logs", controller.AdminGetLogs, middleware.Logged, middleware.EmailVerified, diff --git a/base/utils/query_helper.go b/base/utils/query_helper.go index 2cd9c34f..95df35d1 100644 --- a/base/utils/query_helper.go +++ b/base/utils/query_helper.go @@ -2,15 +2,16 @@ package utils import ( "fmt" - "github.com/EduOJ/backend/base" - "github.com/EduOJ/backend/database/models" - "github.com/pkg/errors" - "gorm.io/gorm" "net/http" "net/url" "reflect" "strconv" "strings" + + "github.com/EduOJ/backend/base" + "github.com/EduOJ/backend/database/models" + "github.com/pkg/errors" + "gorm.io/gorm" ) func Paginator(query *gorm.DB, limit, offset int, requestURL *url.URL, output interface{}) (total int, prevUrl, nextUrl *string, err error) { @@ -137,6 +138,20 @@ func FindProblem(id string, user *models.User) (*models.Problem, error) { return &problem, nil } +func FindSolution(id string) (*models.Solution, error) { + solution := models.Solution{} + query := base.DB + err := query.Where("id = ?", id).First(&solution).Error + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, err + } else { + return nil, errors.Wrap(err, "could not query solution") + } + } + return &solution, nil +} + // This function checks if the user has permission to get problems which are not public. // nil user pointer is regarded as admin(skip the permission judgement). func FindTestCase(problemId string, testCaseIdStr string, user *models.User) (*models.TestCase, *models.Problem, error) { diff --git a/database.db b/database.db new file mode 100644 index 00000000..c422fa41 Binary files /dev/null and b/database.db differ diff --git a/database/migrate.go b/database/migrate.go index 45a24bf1..4e29f2af 100644 --- a/database/migrate.go +++ b/database/migrate.go @@ -2,13 +2,14 @@ package database import ( "fmt" + "time" + "github.com/EduOJ/backend/base" "github.com/go-gormigrate/gormigrate/v2" "github.com/pkg/errors" "github.com/spf13/viper" "gorm.io/datatypes" "gorm.io/gorm" - "time" ) func GetMigration() *gormigrate.Gormigrate { @@ -337,6 +338,69 @@ func GetMigration() *gormigrate.Gormigrate { return }, }, + // add solutions + { + ID: "add_solutions", + Migrate: func(tx *gorm.DB) (err error) { + + type Solution struct { + ID uint `gorm:"primaryKey" json:"id"` + + ProblemID uint `json:"problem_id"` + Name string `sql:"index" json:"name"` + Author string `sql:"index" json:"auther"` + Description string `json:"description"` + Likes string `json:"likes"` + + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"-"` + DeletedAt gorm.DeletedAt `json:"deleted_at"` + } + err = tx.AutoMigrate(&Solution{}) + if err != nil { + return + } + return + }, + Rollback: func(tx *gorm.DB) (err error) { + err = tx.Migrator().DropTable("solutions") + if err != nil { + return + } + return + }, + }, + // add solution_comments + { + ID: "add_solution_comments", + Migrate: func(tx *gorm.DB) (err error) { + + type SolutionComment struct { + ID uint `gorm:"primaryKey" json:"id"` + + SolutionID uint `sql:"index" json:"solution_id"` + FatherNode uint `json:"father_node"` + Description string `json:"description"` + Speaker string `json:"speaker"` + + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"-"` + DeletedAt gorm.DeletedAt `json:"deleted_at"` + } + err = tx.AutoMigrate(&SolutionComment{}) + if err != nil { + return + } + return + }, + Rollback: func(tx *gorm.DB) (err error) { + err = tx.Migrator().DropTable("solution_comments") + if err != nil { + return + } + return + }, + }, { // add default problem role ID: "add_default_problem_role", diff --git a/database/models/solution.go b/database/models/solution.go new file mode 100644 index 00000000..1fa5ce78 --- /dev/null +++ b/database/models/solution.go @@ -0,0 +1,34 @@ +package models + +import ( + "time" + + "gorm.io/gorm" +) + +type Solution struct { + ID uint `gorm:"primaryKey" json:"id"` + + ProblemID uint `sql:"index" json:"problem_id"` + Name string `json:"name"` + Author string `json:"auther"` + Description string `json:"description"` + Likes string `json:"likes"` + + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"-"` + DeletedAt gorm.DeletedAt `json:"deleted_at"` +} + +type Likes struct { + Count int `json:"count"` + IsLike bool `json:"isLike"` +} + +func (s Solution) GetID() uint { + return s.ID +} + +func (s Solution) GetProblemID() uint { + return s.ProblemID +} diff --git a/database/models/solution_comment.go b/database/models/solution_comment.go new file mode 100644 index 00000000..4ed5a073 --- /dev/null +++ b/database/models/solution_comment.go @@ -0,0 +1,55 @@ +package models + +import ( + "time" + + "gorm.io/gorm" +) + +type SolutionComment struct { + ID uint `gorm:"primaryKey" json:"id"` + + SolutionID uint `sql:"index" json:"solution_id" gorm:"not null"` + FatherNode uint `json:"father_node" gorm:"not null"` + Description string `json:"description"` + Speaker string `json:"speaker"` + + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + DeletedAt gorm.DeletedAt `json:"deleted_at"` +} + +type SolutionCommentNode struct { + ID uint `gorm:"primaryKey" json:"id"` + + SolutionID uint `sql:"index" json:"solution_id" gorm:"not null"` + FatherNode uint `json:"father_node" gorm:"not null"` + Description string `json:"description"` + Speaker string `json:"speaker"` + + Kids []SolutionCommentNode `json:"kids"` + + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"-"` + DeletedAt gorm.DeletedAt `json:"deleted_at"` +} + +type SolutionCommentTree struct { + Roots []SolutionCommentNode `json:"roots"` + + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"-"` + DeletedAt gorm.DeletedAt `json:"deleted_at"` +} + +func (sc SolutionComment) GetID() uint { + return sc.ID +} + +func (sc SolutionComment) GetSolutionID() uint { + return sc.SolutionID +} + +func (sc SolutionComment) GetFatherNode() uint { + return sc.FatherNode +}