mirror of
				https://github.com/aykhans/slash-e.git
				synced 2025-11-04 10:49:58 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			206 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			206 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package v2
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"time"
 | 
						|
 | 
						|
	"google.golang.org/grpc/codes"
 | 
						|
	"google.golang.org/grpc/status"
 | 
						|
	"google.golang.org/protobuf/types/known/timestamppb"
 | 
						|
 | 
						|
	apiv2pb "github.com/boojack/slash/proto/gen/api/v2"
 | 
						|
	storepb "github.com/boojack/slash/proto/gen/store"
 | 
						|
	"github.com/boojack/slash/server/metric"
 | 
						|
	"github.com/boojack/slash/store"
 | 
						|
)
 | 
						|
 | 
						|
func (s *APIV2Service) ListCollections(ctx context.Context, _ *apiv2pb.ListCollectionsRequest) (*apiv2pb.ListCollectionsResponse, error) {
 | 
						|
	userID := ctx.Value(userIDContextKey).(int32)
 | 
						|
	find := &store.FindCollection{}
 | 
						|
	find.CreatorID = &userID
 | 
						|
	collections, err := s.Store.ListCollections(ctx, find)
 | 
						|
	if err != nil {
 | 
						|
		return nil, status.Errorf(codes.Internal, "failed to get collection list, err: %v", err)
 | 
						|
	}
 | 
						|
 | 
						|
	convertedCollections := []*apiv2pb.Collection{}
 | 
						|
	for _, collection := range collections {
 | 
						|
		convertedCollections = append(convertedCollections, convertCollectionFromStore(collection))
 | 
						|
	}
 | 
						|
 | 
						|
	response := &apiv2pb.ListCollectionsResponse{
 | 
						|
		Collections: convertedCollections,
 | 
						|
	}
 | 
						|
	return response, nil
 | 
						|
}
 | 
						|
 | 
						|
func (s *APIV2Service) GetCollection(ctx context.Context, request *apiv2pb.GetCollectionRequest) (*apiv2pb.GetCollectionResponse, error) {
 | 
						|
	collection, err := s.Store.GetCollection(ctx, &store.FindCollection{
 | 
						|
		ID: &request.Id,
 | 
						|
	})
 | 
						|
	if err != nil {
 | 
						|
		return nil, status.Errorf(codes.Internal, "failed to get collection by name: %v", err)
 | 
						|
	}
 | 
						|
	if collection == nil {
 | 
						|
		return nil, status.Errorf(codes.NotFound, "collection not found")
 | 
						|
	}
 | 
						|
 | 
						|
	userID := ctx.Value(userIDContextKey).(int32)
 | 
						|
	if collection.Visibility == storepb.Visibility_PRIVATE && collection.CreatorId != userID {
 | 
						|
		return nil, status.Errorf(codes.PermissionDenied, "Permission denied")
 | 
						|
	}
 | 
						|
	response := &apiv2pb.GetCollectionResponse{
 | 
						|
		Collection: convertCollectionFromStore(collection),
 | 
						|
	}
 | 
						|
	return response, nil
 | 
						|
}
 | 
						|
 | 
						|
func (s *APIV2Service) GetCollectionByName(ctx context.Context, request *apiv2pb.GetCollectionByNameRequest) (*apiv2pb.GetCollectionByNameResponse, error) {
 | 
						|
	collection, err := s.Store.GetCollection(ctx, &store.FindCollection{
 | 
						|
		Name: &request.Name,
 | 
						|
	})
 | 
						|
	if err != nil {
 | 
						|
		return nil, status.Errorf(codes.Internal, "failed to get collection by name: %v", err)
 | 
						|
	}
 | 
						|
	if collection == nil {
 | 
						|
		return nil, status.Errorf(codes.NotFound, "collection not found")
 | 
						|
	}
 | 
						|
 | 
						|
	userID, ok := ctx.Value(userIDContextKey).(int32)
 | 
						|
	if ok {
 | 
						|
		if collection.Visibility == storepb.Visibility_PRIVATE && collection.CreatorId != userID {
 | 
						|
			return nil, status.Errorf(codes.PermissionDenied, "Permission denied")
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
		if collection.Visibility != storepb.Visibility_PUBLIC {
 | 
						|
			return nil, status.Errorf(codes.PermissionDenied, "Permission denied")
 | 
						|
		}
 | 
						|
	}
 | 
						|
	response := &apiv2pb.GetCollectionByNameResponse{
 | 
						|
		Collection: convertCollectionFromStore(collection),
 | 
						|
	}
 | 
						|
	metric.Enqueue("collection view")
 | 
						|
	return response, nil
 | 
						|
}
 | 
						|
 | 
						|
func (s *APIV2Service) CreateCollection(ctx context.Context, request *apiv2pb.CreateCollectionRequest) (*apiv2pb.CreateCollectionResponse, error) {
 | 
						|
	userID := ctx.Value(userIDContextKey).(int32)
 | 
						|
	collection := &storepb.Collection{
 | 
						|
		CreatorId:   userID,
 | 
						|
		Name:        request.Collection.Name,
 | 
						|
		Title:       request.Collection.Title,
 | 
						|
		Description: request.Collection.Description,
 | 
						|
		ShortcutIds: request.Collection.ShortcutIds,
 | 
						|
		Visibility:  storepb.Visibility(request.Collection.Visibility),
 | 
						|
	}
 | 
						|
	collection, err := s.Store.CreateCollection(ctx, collection)
 | 
						|
	if err != nil {
 | 
						|
		return nil, status.Errorf(codes.Internal, "failed to create collection, err: %v", err)
 | 
						|
	}
 | 
						|
 | 
						|
	response := &apiv2pb.CreateCollectionResponse{
 | 
						|
		Collection: convertCollectionFromStore(collection),
 | 
						|
	}
 | 
						|
	metric.Enqueue("collection create")
 | 
						|
	return response, nil
 | 
						|
}
 | 
						|
 | 
						|
func (s *APIV2Service) UpdateCollection(ctx context.Context, request *apiv2pb.UpdateCollectionRequest) (*apiv2pb.UpdateCollectionResponse, error) {
 | 
						|
	if request.UpdateMask == nil || len(request.UpdateMask.Paths) == 0 {
 | 
						|
		return nil, status.Errorf(codes.InvalidArgument, "updateMask is required")
 | 
						|
	}
 | 
						|
 | 
						|
	userID := ctx.Value(userIDContextKey).(int32)
 | 
						|
	currentUser, err := s.Store.GetUser(ctx, &store.FindUser{
 | 
						|
		ID: &userID,
 | 
						|
	})
 | 
						|
	if err != nil {
 | 
						|
		return nil, status.Errorf(codes.Internal, "failed to get current user, err: %v", err)
 | 
						|
	}
 | 
						|
	collection, err := s.Store.GetCollection(ctx, &store.FindCollection{
 | 
						|
		ID: &request.Collection.Id,
 | 
						|
	})
 | 
						|
	if err != nil {
 | 
						|
		return nil, status.Errorf(codes.Internal, "failed to get collection by name: %v", err)
 | 
						|
	}
 | 
						|
	if collection == nil {
 | 
						|
		return nil, status.Errorf(codes.NotFound, "collection not found")
 | 
						|
	}
 | 
						|
	if collection.CreatorId != userID && currentUser.Role != store.RoleAdmin {
 | 
						|
		return nil, status.Errorf(codes.PermissionDenied, "Permission denied")
 | 
						|
	}
 | 
						|
 | 
						|
	update := &store.UpdateCollection{
 | 
						|
		ID: collection.Id,
 | 
						|
	}
 | 
						|
	for _, path := range request.UpdateMask.Paths {
 | 
						|
		switch path {
 | 
						|
		case "name":
 | 
						|
			update.Name = &request.Collection.Name
 | 
						|
		case "title":
 | 
						|
			update.Title = &request.Collection.Title
 | 
						|
		case "description":
 | 
						|
			update.Description = &request.Collection.Description
 | 
						|
		case "shortcut_ids":
 | 
						|
			update.ShortcutIDs = request.Collection.ShortcutIds
 | 
						|
		case "visibility":
 | 
						|
			visibility := store.Visibility(request.Collection.Visibility.String())
 | 
						|
			update.Visibility = &visibility
 | 
						|
		}
 | 
						|
	}
 | 
						|
	collection, err = s.Store.UpdateCollection(ctx, update)
 | 
						|
	if err != nil {
 | 
						|
		return nil, status.Errorf(codes.Internal, "failed to update collection, err: %v", err)
 | 
						|
	}
 | 
						|
 | 
						|
	response := &apiv2pb.UpdateCollectionResponse{
 | 
						|
		Collection: convertCollectionFromStore(collection),
 | 
						|
	}
 | 
						|
	return response, nil
 | 
						|
}
 | 
						|
 | 
						|
func (s *APIV2Service) DeleteCollection(ctx context.Context, request *apiv2pb.DeleteCollectionRequest) (*apiv2pb.DeleteCollectionResponse, error) {
 | 
						|
	userID := ctx.Value(userIDContextKey).(int32)
 | 
						|
	currentUser, err := s.Store.GetUser(ctx, &store.FindUser{
 | 
						|
		ID: &userID,
 | 
						|
	})
 | 
						|
	if err != nil {
 | 
						|
		return nil, status.Errorf(codes.Internal, "failed to get current user, err: %v", err)
 | 
						|
	}
 | 
						|
	collection, err := s.Store.GetCollection(ctx, &store.FindCollection{
 | 
						|
		ID: &request.Id,
 | 
						|
	})
 | 
						|
	if err != nil {
 | 
						|
		return nil, status.Errorf(codes.Internal, "failed to get collection by name: %v", err)
 | 
						|
	}
 | 
						|
	if collection == nil {
 | 
						|
		return nil, status.Errorf(codes.NotFound, "collection not found")
 | 
						|
	}
 | 
						|
	if collection.CreatorId != userID && currentUser.Role != store.RoleAdmin {
 | 
						|
		return nil, status.Errorf(codes.PermissionDenied, "Permission denied")
 | 
						|
	}
 | 
						|
 | 
						|
	err = s.Store.DeleteCollection(ctx, &store.DeleteCollection{
 | 
						|
		ID: collection.Id,
 | 
						|
	})
 | 
						|
	if err != nil {
 | 
						|
		return nil, status.Errorf(codes.Internal, "failed to delete collection, err: %v", err)
 | 
						|
	}
 | 
						|
	response := &apiv2pb.DeleteCollectionResponse{}
 | 
						|
	return response, nil
 | 
						|
}
 | 
						|
 | 
						|
func convertCollectionFromStore(collection *storepb.Collection) *apiv2pb.Collection {
 | 
						|
	return &apiv2pb.Collection{
 | 
						|
		Id:          collection.Id,
 | 
						|
		CreatorId:   collection.CreatorId,
 | 
						|
		CreatedTime: timestamppb.New(time.Unix(collection.CreatedTs, 0)),
 | 
						|
		UpdatedTime: timestamppb.New(time.Unix(collection.UpdatedTs, 0)),
 | 
						|
		Name:        collection.Name,
 | 
						|
		Title:       collection.Title,
 | 
						|
		Description: collection.Description,
 | 
						|
		ShortcutIds: collection.ShortcutIds,
 | 
						|
		Visibility:  apiv2pb.Visibility(collection.Visibility),
 | 
						|
	}
 | 
						|
}
 |