ronantakizawa/codereview-bench huggingface dataset:
Repository: usememos/memos
File: web/src/components/Dialog/BaseDialog.tsx (TypeScript)

Code before:
import { useEffect } from "react";
import { createRoot } from "react-dom/client";
import { Provider } from "react-redux";
import { ANIMATION_DURATION } from "../../helpers/consts";
import store from "../../store";
import { useDialogStore } from "../../store/module/dialog";
import "../../less/base-dialog.less";
import { CssVarsProvider } from "@mui/joy";
import theme from "../../theme";

interface DialogConfig {
  className: string;
  clickSpaceDestroy?: boolean;
  dialogName: string;
}

interface Props extends DialogConfig, DialogProps {
  children: React.ReactNode;
}

const BaseDialog: React.FC<Props> = (props: Props) => {
  const { children, className, clickSpaceDestroy, dialogName, destroy } = props;
  const dialogStore = useDialogStore();
  useEffect(() => {
    dialogStore.pushDialogStack(dialogName);
    const handleKeyDown = (event: KeyboardEvent) => {
      if (event.code === "Escape") {
        if (dialogName === dialogStore.topDialogStack()) {
          dialogStore.popDialogStack();
          destroy();
        }
      }
    };

    document.body.addEventListener("keydown", handleKeyDown);

    return () => {
      document.body.removeEventListener("keydown", handleKeyDown);
    };
  }, []);

  const handleSpaceClicked = () => {
    if (clickSpaceDestroy) {
      destroy();
    }
  };

  return (

Review comment (suggestion):
```suggestion
  const dialogStore = useDialogStore();

```

Code after:
import { useEffect } from "react";
import { createRoot } from "react-dom/client";
import { Provider } from "react-redux";
import { ANIMATION_DURATION } from "../../helpers/consts";
import store from "../../store";
import { useDialogStore } from "../../store/module";
import { CssVarsProvider } from "@mui/joy";
import theme from "../../theme";
import "../../less/base-dialog.less";

interface DialogConfig {
  className: string;
  clickSpaceDestroy?: boolean;
  dialogName: string;
}

interface Props extends DialogConfig, DialogProps {
  children: React.ReactNode;
}

const BaseDialog: React.FC<Props> = (props: Props) => {
  const { children, className, clickSpaceDestroy, dialogName, destroy } = props;
  const dialogStore = useDialogStore();

  useEffect(() => {
    dialogStore.pushDialogStack(dialogName);
    const handleKeyDown = (event: KeyboardEvent) => {
      if (event.code === "Escape") {
        if (dialogName === dialogStore.topDialogStack()) {
          dialogStore.popDialogStack();
          destroy();
        }
      }
    };

    document.body.addEventListener("keydown", handleKeyDown);

    return () => {
      document.body.removeEventListener("keydown", handleKeyDown);
    };
  }, []);

  const handleSpaceClicked = () => {
    if (clickSpaceDestroy) {
      destroy();
    }
  };
Repository: usememos/memos
File: web/src/components/Dialog/BaseDialog.tsx (TypeScript)

Code before:
import { useEffect } from "react";
import { createRoot } from "react-dom/client";
import { Provider } from "react-redux";
import { ANIMATION_DURATION } from "../../helpers/consts";
import store from "../../store";
import { useDialogStore } from "../../store/module/dialog";
import "../../less/base-dialog.less";
import { CssVarsProvider } from "@mui/joy";
import theme from "../../theme";

interface DialogConfig {
  className: string;
  clickSpaceDestroy?: boolean;
  dialogName: string;
}

interface Props extends DialogConfig, DialogProps {
  children: React.ReactNode;
}

const BaseDialog: React.FC<Props> = (props: Props) => {
  const { children, className, clickSpaceDestroy, dialogName, destroy } = props;
  const dialogStore = useDialogStore();
  useEffect(() => {
    dialogStore.pushDialogStack(dialogName);
    const handleKeyDown = (event: KeyboardEvent) => {
      if (event.code === "Escape") {
        if (dialogName === dialogStore.topDialogStack()) {
          dialogStore.popDialogStack();
          destroy();
        }

Review comment (suggestion):
export `useDialogStore` in [index.ts](https://github.com/usememos/memos/blob/main/web/src/store/module/index.ts)

```suggestion
import { useDialogStore } from "../../store/module";
```

Code after:
import { useEffect } from "react";
import { createRoot } from "react-dom/client";
import { Provider } from "react-redux";
import { ANIMATION_DURATION } from "../../helpers/consts";
import store from "../../store";
import { useDialogStore } from "../../store/module";
import { CssVarsProvider } from "@mui/joy";
import theme from "../../theme";
import "../../less/base-dialog.less";

interface DialogConfig {
  className: string;
  clickSpaceDestroy?: boolean;
  dialogName: string;
}

interface Props extends DialogConfig, DialogProps {
  children: React.ReactNode;
}

const BaseDialog: React.FC<Props> = (props: Props) => {
  const { children, className, clickSpaceDestroy, dialogName, destroy } = props;
  const dialogStore = useDialogStore();

  useEffect(() => {
    dialogStore.pushDialogStack(dialogName);
    const handleKeyDown = (event: KeyboardEvent) => {
      if (event.code === "Escape") {
        if (dialogName === dialogStore.topDialogStack()) {
          dialogStore.popDialogStack();
          destroy();
Repository: usememos/memos
File: server/system.go (Go)

Code before:
		systemSettingList, err := s.Store.FindSystemSettingList(ctx, &api.SystemSettingFind{})
		if err != nil {
			return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find system setting list").SetInternal(err)
		}

		c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8)
		if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(systemSettingList)); err != nil {
			return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode system setting list response").SetInternal(err)
		}
		return nil
	})

	g.POST("/system/vacuum", func(c echo.Context) error {
		ctx := c.Request().Context()
		userID, ok := c.Get(getUserIDContextKey()).(int)
		if !ok {
			return echo.NewHTTPError(http.StatusUnauthorized, "Missing user in session")
		}
		user, err := s.Store.FindUser(ctx, &api.UserFind{
			ID: &userID,
		})
		if err != nil {
			return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find user").SetInternal(err)
		}
		if user == nil || user.Role != api.Host {
			// throw error
		}
		if err := s.Store.Vacuum(ctx); err != nil {
			return echo.NewHTTPError(http.StatusInternalServerError, "Failed to vacuum database").SetInternal(err)
		}
		c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8)
		return nil
	})
}


Review comment (security):
```suggestion
			return echo.NewHTTPError(http.StatusUnauthorized, "Unauthorized")
```

Code after:
		systemSettingList, err := s.Store.FindSystemSettingList(ctx, &api.SystemSettingFind{})
		if err != nil {
			return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find system setting list").SetInternal(err)
		}

		c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8)
		if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(systemSettingList)); err != nil {
			return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode system setting list response").SetInternal(err)
		}
		return nil
	})

	g.POST("/system/vacuum", func(c echo.Context) error {
		ctx := c.Request().Context()
		userID, ok := c.Get(getUserIDContextKey()).(int)
		if !ok {
			return echo.NewHTTPError(http.StatusUnauthorized, "Missing user in session")
		}
		user, err := s.Store.FindUser(ctx, &api.UserFind{
			ID: &userID,
		})
		if err != nil {
			return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find user").SetInternal(err)
		}
		if user == nil || user.Role != api.Host {
			return echo.NewHTTPError(http.StatusUnauthorized, "Unauthorized")
		}
		if err := s.Store.Vacuum(ctx); err != nil {
			return echo.NewHTTPError(http.StatusInternalServerError, "Failed to vacuum database").SetInternal(err)
		}
		c.Response().WriteHeader(http.StatusOK)
		return nil
	})
}
Repository: usememos/memos
File: web/src/helpers/api.ts (TypeScript)

Code before:
import axios from "axios";

type ResponseObject<T> = {
  data: T;
  error?: string;
  message?: string;
};

export function getSystemStatus() {
  return axios.get<ResponseObject<SystemStatus>>("/api/status");
}

export function upsertSystemSetting(systemSetting: SystemSetting) {
  return axios.post<ResponseObject<SystemSetting>>("/api/system/setting", systemSetting);
}

export function vacuumDatabase() {
  return axios.post<ResponseObject<SystemStatus>>("/api/system/vacuum");
}

export function signin(username: string, password: string) {
  return axios.post<ResponseObject<User>>("/api/auth/signin", {
    username,
    password,
  });
}

export function signup(username: string, password: string, role: UserRole) {
  return axios.post<ResponseObject<User>>("/api/auth/signup", {
    username,
    password,
    role,
  });
}

export function signout() {
  return axios.post("/api/auth/logout");
}

export function createUser(userCreate: UserCreate) {
  return axios.post<ResponseObject<User>>("/api/user", userCreate);
}


Review comment (suggestion):
```suggestion
  return axios.post("/api/system/vacuum");
```

Code after:
import axios from "axios";

type ResponseObject<T> = {
  data: T;
  error?: string;
  message?: string;
};

export function getSystemStatus() {
  return axios.get<ResponseObject<SystemStatus>>("/api/status");
}

export function upsertSystemSetting(systemSetting: SystemSetting) {
  return axios.post<ResponseObject<SystemSetting>>("/api/system/setting", systemSetting);
}

export function vacuumDatabase() {
  return axios.post("/api/system/vacuum");
}

export function signin(username: string, password: string) {
  return axios.post<ResponseObject<User>>("/api/auth/signin", {
    username,
    password,
  });
}

export function signup(username: string, password: string, role: UserRole) {
  return axios.post<ResponseObject<User>>("/api/auth/signup", {
    username,
    password,
    role,
  });
}

export function signout() {
  return axios.post("/api/auth/logout");
}

export function createUser(userCreate: UserCreate) {
  return axios.post<ResponseObject<User>>("/api/user", userCreate);
}
Repository: usememos/memos
File: server/system.go (Go)

Code before:
		c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8)
		if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(systemSettingList)); err != nil {
			return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode system setting list response").SetInternal(err)
		}
		return nil
	})

	g.POST("/system/vacuum", func(c echo.Context) error {
		ctx := c.Request().Context()
		userID, ok := c.Get(getUserIDContextKey()).(int)
		if !ok {
			return echo.NewHTTPError(http.StatusUnauthorized, "Missing user in session")
		}
		user, err := s.Store.FindUser(ctx, &api.UserFind{
			ID: &userID,
		})
		if err != nil {
			return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find user").SetInternal(err)
		}
		if user == nil || user.Role != api.Host {
			return echo.NewHTTPError(http.StatusUnauthorized, "Unauthorized")
		}
		if err := s.Store.Vacuum(ctx); err != nil {
			return echo.NewHTTPError(http.StatusInternalServerError, "Failed to vacuum database").SetInternal(err)
		}
		c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8)
		return nil
	})
}


Review comment (suggestion):
```suggestion
		c.Response().WriteHeader(http.StatusOK)
```

Code after:
		c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8)
		if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(systemSettingList)); err != nil {
			return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode system setting list response").SetInternal(err)
		}
		return nil
	})

	g.POST("/system/vacuum", func(c echo.Context) error {
		ctx := c.Request().Context()
		userID, ok := c.Get(getUserIDContextKey()).(int)
		if !ok {
			return echo.NewHTTPError(http.StatusUnauthorized, "Missing user in session")
		}
		user, err := s.Store.FindUser(ctx, &api.UserFind{
			ID: &userID,
		})
		if err != nil {
			return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find user").SetInternal(err)
		}
		if user == nil || user.Role != api.Host {
			return echo.NewHTTPError(http.StatusUnauthorized, "Unauthorized")
		}
		if err := s.Store.Vacuum(ctx); err != nil {
			return echo.NewHTTPError(http.StatusInternalServerError, "Failed to vacuum database").SetInternal(err)
		}
		c.Response().WriteHeader(http.StatusOK)
		return nil
	})
}
Repository: usememos/memos
File: store/db/migration/dev/LATEST__SCHEMA.sql (SQL)

Code before:
  UNIQUE(name, creator_id)
);

-- activity
CREATE TABLE activity (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  creator_id INTEGER NOT NULL,
  created_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')),
  type TEXT NOT NULL DEFAULT '',
  level TEXT NOT NULL CHECK (level IN ('INFO', 'WARN', 'ERROR')) DEFAULT 'INFO',
  payload TEXT NOT NULL DEFAULT '{}'
);

-- storage
CREATE TABLE storage (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  creator_id INTEGER NOT NULL,
  created_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')),
  updated_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')),
  name TEXT NOT NULL DEFAULT '' UNIQUE,
  end_point TEXT NOT NULL DEFAULT '',
  region TEXT NOT NULL DEFAULT '',
  access_key TEXT NOT NULL DEFAULT '',
  secret_key TEXT NOT NULL DEFAULT '',
  bucket TEXT NOT NULL DEFAULT '',
  urlPrefix TEXT NOT NULL DEFAULT ''
);

Review comment (suggestion):
```suggestion
  url_prefix TEXT NOT NULL DEFAULT ''
```

Code after:
  UNIQUE(name, creator_id)
);

-- activity
CREATE TABLE activity (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  creator_id INTEGER NOT NULL,
  created_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')),
  type TEXT NOT NULL DEFAULT '',
  level TEXT NOT NULL CHECK (level IN ('INFO', 'WARN', 'ERROR')) DEFAULT 'INFO',
  payload TEXT NOT NULL DEFAULT '{}'
);

-- storage
CREATE TABLE storage (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  creator_id INTEGER NOT NULL,
  created_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')),
  updated_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')),
  name TEXT NOT NULL DEFAULT '' UNIQUE,
  end_point TEXT NOT NULL DEFAULT '',
  region TEXT NOT NULL DEFAULT '',
  access_key TEXT NOT NULL DEFAULT '',
  secret_key TEXT NOT NULL DEFAULT '',
  bucket TEXT NOT NULL DEFAULT '',
  url_prefix TEXT NOT NULL DEFAULT ''
);
Repository: usememos/memos
File: plugin/storage/s3/s3.go (Go)

Code before:
package s3

import (
	"context"
	"fmt"
	"io"

	"github.com/aws/aws-sdk-go-v2/aws"
	"github.com/aws/aws-sdk-go-v2/config"
	"github.com/aws/aws-sdk-go-v2/credentials"
	"github.com/aws/aws-sdk-go-v2/feature/s3/manager"
	awss3 "github.com/aws/aws-sdk-go-v2/service/s3"
	"github.com/aws/aws-sdk-go-v2/service/s3/types"
	"github.com/usememos/memos/api"
)

type Client struct {
	Client     *awss3.Client
	BucketName string
	URLPrefix  string
}

func NewClient(ctx context.Context, storage *api.Storage) (*Client, error) {
	r2Resolver := aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) {
		return aws.Endpoint{
			URL:           storage.EndPoint,
			SigningRegion: storage.Region,
		}, nil
	})

	cfg, err := config.LoadDefaultConfig(ctx,
		config.WithEndpointResolverWithOptions(r2Resolver),
		config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(storage.AccessKey, storage.SecretKey, "")),
	)
	if err != nil {
		return nil, err
	}

	client := awss3.NewFromConfig(cfg)

	return &Client{
		Client:     client,
		BucketName: storage.Bucket,
		URLPrefix:  storage.URLPrefix,
	}, nil
}

func UploadFile(ctx context.Context, client *Client, filename string, fileType string, src io.Reader, storage *api.Storage) (*string, error) {
	uploader := manager.NewUploader(client.Client)

Review comment (suggestion):
```suggestion
	resolver := aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) {
```

Code after:
package s3

import (
	"context"
	"fmt"
	"io"

	"github.com/aws/aws-sdk-go-v2/aws"
	"github.com/aws/aws-sdk-go-v2/config"
	"github.com/aws/aws-sdk-go-v2/credentials"
	"github.com/aws/aws-sdk-go-v2/feature/s3/manager"
	awss3 "github.com/aws/aws-sdk-go-v2/service/s3"
	"github.com/aws/aws-sdk-go-v2/service/s3/types"
	"github.com/usememos/memos/api"
)

type Client struct {
	Client     *awss3.Client
	BucketName string
	URLPrefix  string
}

func NewClient(ctx context.Context, storage *api.Storage) (*Client, error) {
	resolver := aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) {
		return aws.Endpoint{
			URL:           storage.EndPoint,
			SigningRegion: storage.Region,
		}, nil
	})

	cfg, err := config.LoadDefaultConfig(ctx,
		config.WithEndpointResolverWithOptions(resolver),
		config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(storage.AccessKey, storage.SecretKey, "")),
	)
	if err != nil {
		return nil, err
	}

	client := awss3.NewFromConfig(cfg)

	return &Client{
		Client:     client,
		BucketName: storage.Bucket,
		URLPrefix:  storage.URLPrefix,
	}, nil
}

func (client *Client) UploadFile(ctx context.Context, filename string, fileType string, src io.Reader, storage *api.Storage) (*string, error) {
	uploader := manager.NewUploader(client.Client)
Repository: usememos/memos
File: plugin/storage/s3/s3.go (Go)

Code before:
func NewClient(ctx context.Context, storage *api.Storage) (*Client, error) {
	r2Resolver := aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) {
		return aws.Endpoint{
			URL:           storage.EndPoint,
			SigningRegion: storage.Region,
		}, nil
	})

	cfg, err := config.LoadDefaultConfig(ctx,
		config.WithEndpointResolverWithOptions(r2Resolver),
		config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(storage.AccessKey, storage.SecretKey, "")),
	)
	if err != nil {
		return nil, err
	}

	client := awss3.NewFromConfig(cfg)

	return &Client{
		Client:     client,
		BucketName: storage.Bucket,
		URLPrefix:  storage.URLPrefix,
	}, nil
}

func UploadFile(ctx context.Context, client *Client, filename string, fileType string, src io.Reader, storage *api.Storage) (*string, error) {
	uploader := manager.NewUploader(client.Client)
	resp, err := uploader.Upload(ctx, &awss3.PutObjectInput{
		Bucket:      aws.String(client.BucketName),
		Key:         aws.String(filename),
		Body:        src,
		ContentType: aws.String(fileType),
		ACL:         types.ObjectCannedACL(*aws.String("public-read")),
	})
	if err != nil {
		return nil, err
	}
	var link string
	if storage.URLPrefix == "" {
		link = resp.Location
	} else {
		link = fmt.Sprintf("%s/%s", storage.URLPrefix, filename)
	}
	return &link, nil
}


Review comment (suggestion):
`UploadFile` should be a method of `Client`.

```suggestion
func (client *Client) UploadFile(ctx context.Context, filename string, fileType string, src io.Reader, storage *api.Storage) (*string, error) {
```

Code after:
func NewClient(ctx context.Context, storage *api.Storage) (*Client, error) {
	resolver := aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) {
		return aws.Endpoint{
			URL:           storage.EndPoint,
			SigningRegion: storage.Region,
		}, nil
	})

	cfg, err := config.LoadDefaultConfig(ctx,
		config.WithEndpointResolverWithOptions(resolver),
		config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(storage.AccessKey, storage.SecretKey, "")),
	)
	if err != nil {
		return nil, err
	}

	client := awss3.NewFromConfig(cfg)

	return &Client{
		Client:     client,
		BucketName: storage.Bucket,
		URLPrefix:  storage.URLPrefix,
	}, nil
}

func (client *Client) UploadFile(ctx context.Context, filename string, fileType string, src io.Reader, storage *api.Storage) (*string, error) {
	uploader := manager.NewUploader(client.Client)
	resp, err := uploader.Upload(ctx, &awss3.PutObjectInput{
		Bucket:      aws.String(client.BucketName),
		Key:         aws.String(filename),
		Body:        src,
		ContentType: aws.String(fileType),
		ACL:         types.ObjectCannedACL(*aws.String("public-read")),
	})
	if err != nil {
		return nil, err
	}
	var link string
	if storage.URLPrefix == "" {
		link = resp.Location
	} else {
		link = fmt.Sprintf("%s/%s", storage.URLPrefix, filename)
	}
	return &link, nil
}
Repository: usememos/memos
File: server/rss.go (Go)

Code before:
	}
	return systemStatus.CustomizedProfile, nil
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func getRSSItemTitle(content string) string {
	var title string
	if isTitleDefined(content) {
		title = strings.Split(content, "\n")[0][2:]
	} else {
		title = strings.Split(content, "\n")[0]
		var titleLengthLimit = min(len(title), MaxRSSItemTitleLength)
		if titleLengthLimit < len(title) {
			title = title[:titleLengthLimit] + "..."
		}
	}
	return title
}

func getRssItemDescription(content string) string {
	var description string
	if isTitleDefined(content) {
		var firstLineEnd = strings.Index(content, "\n")
		description = strings.Trim(content[firstLineEnd+1:], " ")
	} else {
		description = content
	}
	return description
}

func isTitleDefined(content string) bool {
	return strings.HasPrefix(content, "# ")
}


Review comment (suggestion):
```suggestion
func getRSSItemDescription(content string) string {
```

Code after:
	}
	return systemStatus.CustomizedProfile, nil
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func getRSSItemTitle(content string) string {
	var title string
	if isTitleDefined(content) {
		title = strings.Split(content, "\n")[0][2:]
	} else {
		title = strings.Split(content, "\n")[0]
		var titleLengthLimit = min(len(title), MaxRSSItemTitleLength)
		if titleLengthLimit < len(title) {
			title = title[:titleLengthLimit] + "..."
		}
	}
	return title
}

func getRSSItemDescription(content string) string {
	var description string
	if isTitleDefined(content) {
		var firstLineEnd = strings.Index(content, "\n")
		description = strings.Trim(content[firstLineEnd+1:], " ")
	} else {
		description = content
	}
	return description
}

func isTitleDefined(content string) bool {
	return strings.HasPrefix(content, "# ")
}