Beispiel #1
0
// HandleChannel handles channel operations
func (c *Controller) HandleChannel(channel *models.Channel) error {
	if channel.TypeConstant != models.Channel_TYPE_GROUP {
		return nil
	}

	chans, err := channel.FetchAllChannelsOfGroup()
	if err != nil {
		return err
	}

	var errs *multierror.Error

	for _, ch := range chans {
		// we'r gonna innore all `not found` errors while deleting datas
		if err := ch.Delete(); err != nil && err != bongo.RecordNotFound {
			errs = multierror.Append(errs, err)
		}

		if err := ch.DeleteChannelParticipants(); err != nil {
			return err
		}

	}

	if errs.ErrorOrNil() != nil {
		return errs
	}

	return nil
}
Beispiel #2
0
func Update(u *url.URL, h http.Header, req *models.Channel, c *models.Context) (int, http.Header, interface{}, error) {
	if !c.IsLoggedIn() {
		return response.NewBadRequest(models.ErrNotLoggedIn)
	}

	id, err := request.GetURIInt64(u, "id")
	if err != nil {
		return response.NewBadRequest(err)
	}
	req.Id = id

	if req.Id == 0 {
		return response.NewBadRequest(err)
	}

	existingOne, err := models.Cache.Channel.ById(id)
	if err != nil {
		return response.NewBadRequest(err)
	}

	participant, err := existingOne.IsParticipant(c.Client.Account.Id)
	if err != nil {
		return response.NewBadRequest(err)
	}
	if !participant {
		return response.NewBadRequest(models.ErrAccountIsNotParticipant)
	}

	// if user is participant in the channel, then user can update only purpose of the channel
	// other fields cannot be updated by participant or anyone else. Only creator can update
	// purpose and other fields of the channel
	if participant {
		if req.Purpose != "" {
			existingOne.Purpose = req.Purpose
		}
	}

	// if user is the creator of the channel, then can update all fields of the channel
	if existingOne.CreatorId == c.Client.Account.Id {
		if req.Name != "" {
			existingOne.Name = req.Name
		}

		// some of the channels stores sparse data
		existingOne.Payload = req.Payload
	}

	// update channel
	if err := existingOne.Update(); err != nil {
		return response.NewBadRequest(err)
	}

	// generate container data
	cc := models.NewChannelContainer()
	if err := cc.PopulateWith(*existingOne, c.Client.Account.Id); err != nil {
		return response.NewBadRequest(err)
	}

	return response.NewOK(cc)
}
Beispiel #3
0
// makeSureMembership checks if the incoming account is a member of the group
// channel that is persisted within incoming session data
func makeSureMembership(groupChannel *models.Channel, accountId int64) error {
	isMember, err := models.Cache.Participant.ByChannelIdAndAccountId(groupChannel.Id, accountId)
	if err != nil {
		return err
	}
	// we dont need to do anything if the user is a member of group channel
	if isMember {
		return nil
	}

	_, err = groupChannel.AddParticipant(accountId)
	if err != nil && err != models.ErrAccountIsAlreadyInTheChannel {
		return err
	}

	return models.Cache.Participant.SetToCache(groupChannel.Id, accountId)
}
Beispiel #4
0
func handleChannelResponse(c models.Channel, q *request.Query) (int, http.Header, interface{}, error) {
	// add troll mode filter
	if c.MetaBits.Is(models.Troll) && !q.ShowExempt {
		return response.NewNotFound()
	}

	canOpen, err := c.CanOpen(q.AccountId)
	if err != nil {
		return response.NewBadRequest(err)
	}

	if !canOpen {
		cp := models.NewChannelParticipant()
		cp.ChannelId = c.Id
		isInvited, err := cp.IsInvited(q.AccountId)
		if err != nil {
			return response.NewBadRequest(err)
		}

		if !isInvited {
			return response.NewAccessDenied(
				fmt.Errorf(
					"account (%d) tried to retrieve the unattended channel (%d)",
					q.AccountId,
					c.Id,
				),
			)
		}
	}

	cc := models.NewChannelContainer()

	if err := cc.Fetch(c.GetId(), q); err != nil {
		return response.NewBadRequest(err)
	}

	cc.AddIsParticipant(q.AccountId)

	// TODO this should be in the channel cache by default
	cc.AddLastMessage(q.AccountId)
	cc.AddUnreadCount(q.AccountId)
	return response.HandleResultAndError(cc, cc.Err)
}
Beispiel #5
0
func Create(u *url.URL, h http.Header, req *models.Channel, context *models.Context) (int, http.Header, interface{}, error) {
	// only logged in users can create a channel
	if !context.IsLoggedIn() {
		return response.NewBadRequest(models.ErrNotLoggedIn)
	}

	// get group name from context
	req.GroupName = context.GroupName
	req.CreatorId = context.Client.Account.Id

	if req.PrivacyConstant == "" {
		req.PrivacyConstant = models.Channel_PRIVACY_PRIVATE

		// if group is koding, then make it public, because it was public before
		if req.GroupName == models.Channel_KODING_NAME {
			req.PrivacyConstant = models.Channel_PRIVACY_PUBLIC
		}
	}

	if req.TypeConstant == "" {
		req.TypeConstant = models.Channel_TYPE_TOPIC
	}

	if err := validateChannelRequest(req); err != nil {
		return response.NewBadRequest(err)
	}

	if err := req.Create(); err != nil {
		return response.NewBadRequest(err)
	}

	if _, err := req.AddParticipant(req.CreatorId); err != nil {
		// channel create works as idempotent, that channel might have been created before
		if err != models.ErrAccountIsAlreadyInTheChannel {
			return response.NewBadRequest(err)
		}
	}

	cc := models.NewChannelContainer()
	if err := cc.PopulateWith(*req, context.Client.Account.Id); err != nil {
		return response.NewBadRequest(err)
	}

	return response.NewOK(cc)
}
Beispiel #6
0
func (f *Controller) fetchNotifiedParticipantIds(c *models.Channel, pe *models.ParticipantEvent, eventName string) ([]int64, error) {
	notifiedParticipantIds := make([]int64, 0)

	// notify added/removed participants
	for _, participant := range pe.Participants {
		notifiedParticipantIds = append(notifiedParticipantIds, participant.AccountId)
	}

	// When a user is removed from a private channel notify all channel participants to
	// make them update their sidebar channel list.
	if eventName == RemovedFromChannelEventName {

		if c.TypeConstant == models.Channel_TYPE_PRIVATE_MESSAGE ||
			c.TypeConstant == models.Channel_TYPE_COLLABORATION {

			participantIds, err := c.FetchParticipantIds(&request.Query{})
			if err != nil {
				return notifiedParticipantIds, err
			}
			notifiedParticipantIds = append(notifiedParticipantIds, participantIds...)
		}
	}
	return notifiedParticipantIds, nil
}
Beispiel #7
0
func Delete(u *url.URL, h http.Header, req *models.Channel, context *models.Context) (int, http.Header, interface{}, error) {
	if !context.IsLoggedIn() {
		return response.NewBadRequest(models.ErrNotLoggedIn)
	}

	id, err := request.GetURIInt64(u, "id")
	if err != nil {
		return response.NewBadRequest(err)
	}

	if err := req.ById(id); err != nil {
		return response.NewBadRequest(err)
	}

	if req.TypeConstant == models.Channel_TYPE_GROUP {
		return response.NewBadRequest(errors.New("You can not delete group channel"))
	}

	canOpen, err := req.CanOpen(context.Client.Account.Id)
	if err != nil {
		return response.NewBadRequest(err)
	}

	if !canOpen {
		return response.NewBadRequest(models.ErrCannotOpenChannel)
	}

	// TO-DO
	// add super-admin check here
	if req.CreatorId != context.Client.Account.Id {
		isAdmin, err := modelhelper.IsAdmin(context.Client.Account.Nick, req.GroupName)
		if err != nil {
			return response.NewBadRequest(err)
		}

		if !isAdmin {
			return response.NewAccessDenied(models.ErrAccessDenied)
		}
	}

	if err := req.Delete(); err != nil {
		return response.NewBadRequest(err)
	}
	// yes it is deleted but not removed completely from our system
	return response.NewDeleted()
}