package grpcserver import ( "context" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/timestamppb" pb "git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v2" "git.wntrmute.dev/kyle/metacrypt/internal/auth" ) type authServer struct { pb.UnimplementedAuthServiceServer s *GRPCServer } func (as *authServer) Login(_ context.Context, req *pb.LoginRequest) (*pb.LoginResponse, error) { token, expiresAtTime, err := as.s.auth.Login(req.Username, req.Password, req.TotpCode) if err != nil { return nil, status.Error(codes.Unauthenticated, "invalid credentials") } var expiresAt *timestamppb.Timestamp if !expiresAtTime.IsZero() { expiresAt = timestamppb.New(expiresAtTime) } as.s.logger.Info("audit: login", "username", req.Username) return &pb.LoginResponse{Token: token, ExpiresAt: expiresAt}, nil } func (as *authServer) Logout(ctx context.Context, _ *pb.LogoutRequest) (*pb.LogoutResponse, error) { token := extractToken(ctx) _ = auth.Logout(as.s.auth, token) as.s.logger.Info("audit: logout", "username", callerUsername(ctx)) return &pb.LogoutResponse{}, nil } func (as *authServer) TokenInfo(ctx context.Context, _ *pb.TokenInfoRequest) (*pb.TokenInfoResponse, error) { ti := tokenInfoFromContext(ctx) if ti == nil { // Shouldn't happen — authInterceptor runs first — but guard anyway. token := extractToken(ctx) var err error ti, err = as.s.auth.ValidateToken(token) if err != nil { return nil, status.Error(codes.Unauthenticated, "invalid token") } } return &pb.TokenInfoResponse{ Username: ti.Username, Roles: ti.Roles, IsAdmin: ti.IsAdmin, }, nil }