Beispiel #1
0
func AddMember(c common.WSContext) error {
	var state GameState
	c.Data().Overwrite(&state)
	return c.Transact(func(c common.WSContext) error {
		game := Game{Id: state.Game.Id}
		if err := c.DB().Get(&game); err != nil {
			return fmt.Errorf("Game not found")
		}
		if game.State != common.GameStateCreated {
			return fmt.Errorf("%+v already started")
		}
		variant, found := common.VariantMap[game.Variant]
		if !found {
			return fmt.Errorf("Unknown variant %v", game.Variant)
		}
		if alreadyMember, err := game.Member(c.DB(), c.Principal()); err != nil {
			return err
		} else if alreadyMember != nil {
			return fmt.Errorf("%+v is already member of %v", alreadyMember, game.Id)
		}
		me := &user.User{Id: kol.Id(c.Principal())}
		if err := c.DB().Get(me); err != nil {
			return err
		}
		if game.Disallows(me) {
			return fmt.Errorf("Is not allowed to join this game due to game settings")
		}
		already, err := game.Members(c.DB())
		if err != nil {
			return err
		}
		if disallows, err := already.Disallows(c.DB(), me); err != nil {
			return err
		} else if disallows {
			return fmt.Errorf("Is not allowed to join this game due to blacklistings")
		}
		if len(already) < len(variant.Nations) {
			member := Member{
				GameId:           state.Game.Id,
				UserId:           kol.Id(c.Principal()),
				PreferredNations: state.Members[0].PreferredNations,
			}
			if err := c.DB().Set(&member); err != nil {
				return err
			}
			if len(already) == len(variant.Nations)-1 {
				if err := game.start(c.Diet()); err != nil {
					return err
				}
				c.Infof("Started %v", game.Id)
			}
		}
		return nil
	})
}
Beispiel #2
0
func Openid(c *common.HTTPContext) (err error) {
	redirect, email, ok, err := gopenid.VerifyAuth(c.Req())
	if err != nil {
		return
	}
	if ok {
		email = strings.ToLower(email)
		c.Session().Values[common.SessionEmail] = email
		u := &User{Id: kol.Id(email)}
		err = c.DB().Get(u)
		if err == kol.NotFound {
			err = nil
			u.Email = email
			u.Ranking = 1
		}
		if err == nil {
			u.Language = common.GetLanguage(c.Req())
			u.DiplicityHost = c.Req().Host
			u.LastLoginAt = time.Now()
			err = c.DB().Set(u)
		}
	} else {
		delete(c.Session().Values, common.SessionEmail)
	}
	c.Close()
	c.Resp().Header().Set("Location", redirect.String())
	c.Resp().WriteHeader(302)
	fmt.Fprintln(c.Resp(), redirect.String())
	return
}
Beispiel #3
0
func Set(d *kol.DB, at time.Duration) (err error) {
	epoch := &Epoch{
		Id: kol.Id(epochKey),
		At: at,
	}
	err = d.Set(epoch)
	return
}
Beispiel #4
0
func (self *cli) createUser(email string) (err error) {
	_, err = self.post("/admin/users", map[string]interface{}{
		"Email":         email,
		"Id":            kol.Id(email),
		"DiplicityHost": fmt.Sprintf("%v:%v", self.host, self.port),
	})
	return
}
Beispiel #5
0
func subscribeOthers(c common.WSContext, filter kol.QFilter, preLimiter func(source Games) (result Games), postLimiter func(source GameStates) (result GameStates)) error {
	if c.Principal() == "" {
		return websocket.JSON.Send(c.Conn(), gosubs.Message{
			Type: gosubs.FetchType,
			Object: &gosubs.Object{
				URI: c.Match()[0],
			},
		})
	}
	s := c.Pack().New(c.Match()[0])
	s.Query = s.DB().Query().Where(filter)
	s.Call = func(i interface{}, op string) error {
		games := i.([]*Game)
		if preLimiter != nil {
			games = ([]*Game)(preLimiter(Games(games)))
		}
		states := GameStates{}
		isMember := false
		me := &user.User{Id: kol.Id(c.Principal())}
		if err := c.DB().Get(me); err != nil {
			return err
		}
		for _, game := range games {
			if !game.Disallows(me) {
				members, err := game.Members(c.DB())
				if err != nil {
					return err
				}
				if disallows, err := members.Disallows(c.DB(), me); err != nil {
					return err
				} else if !disallows {
					isMember = members.Contains(c.Principal())
					if !isMember {
						state, err := game.ToState(c.DB(), members, nil)
						if err != nil {
							return err
						}
						states = append(states, state)
					}
				}
			}
		}
		if op == gosubs.FetchType || len(states) > 0 {
			if postLimiter != nil {
				states = postLimiter(states)
			}
			return s.Send(states, op)
		}
		return nil
	}
	return s.Subscribe(&Game{})
}
Beispiel #6
0
func OAuth2Callback(clientId, clientSecret string) func(c *common.HTTPContext) (err error) {
	return func(c *common.HTTPContext) (err error) {
		state := c.Req().FormValue("state")
		nonceLock.Lock()
		defer nonceLock.Unlock()
		if _, found := nonces[state]; !found {
			err = fmt.Errorf("state not found")
			return
		}
		delete(nonces, state)

		scheme := "http"
		if c.Req().TLS != nil {
			scheme = "https"
		}
		redirectUrl, err := url.Parse(fmt.Sprintf("%v://%v/oauth2callback", scheme, c.Req().Host))
		if err != nil {
			return
		}
		email, ok, err := goauth2.VerifyEmail(clientId, clientSecret, c.Req().FormValue("code"), redirectUrl)
		if err != nil {
			return
		}

		if ok {
			email = strings.ToLower(email)
			c.Session().Values[common.SessionEmail] = email
			u := &User{Id: kol.Id(email)}
			err = c.DB().Get(u)
			if err == kol.NotFound {
				err = nil
				u.Email = email
				u.Ranking = 1
			}
			if err == nil {
				u.Language = common.GetLanguage(c.Req())
				u.DiplicityHost = c.Req().Host
				u.LastLoginAt = time.Now()
				err = c.DB().Set(u)
			}
		} else {
			delete(c.Session().Values, common.SessionEmail)
		}
		c.Close()
		c.Resp().Header().Set("Location", "/")
		c.Resp().WriteHeader(302)
		fmt.Fprintln(c.Resp(), "/")
		return
	}
}
Beispiel #7
0
func Get(d *kol.DB) (result time.Duration, err error) {
	epoch := &Epoch{
		Id: kol.Id(epochKey),
	}
	if err = d.Get(epoch); err != nil {
		if err == kol.NotFound {
			err = nil
		} else {
			return
		}
	}
	result = epoch.At + time.Now().Sub(time.Unix(0, atomic.LoadInt64(&deltaPoint)))
	return
}
Beispiel #8
0
func (self Members) ToStates(d *kol.DB, g *Game, email string, isAdmin bool) (result []MemberState, err error) {
	result = make([]MemberState, len(self))
	isMember := false
	for _, member := range self {
		if member.UserId.Equals(kol.Id(email)) {
			isMember = true
			break
		}
	}
	for index, member := range self {
		var state *MemberState
		if state, err = member.ToState(d, g, email, isMember, isAdmin); err != nil {
			return
		}
		result[index] = *state
	}
	return
}
Beispiel #9
0
func Create(c common.WSContext) error {
	var state GameState
	c.Data().Overwrite(&state)

	game := &Game{
		Variant:               state.Game.Variant,
		EndYear:               state.Game.EndYear,
		Private:               state.Game.Private,
		SecretEmail:           state.Game.SecretEmail,
		SecretNickname:        state.Game.SecretNickname,
		SecretNation:          state.Game.SecretNation,
		Deadlines:             state.Game.Deadlines,
		ChatFlags:             state.Game.ChatFlags,
		AllocationMethod:      state.Game.AllocationMethod,
		NonCommitConsequences: state.Game.NonCommitConsequences,
		NMRConsequences:       state.Game.NMRConsequences,
		Ranking:               state.Game.Ranking,
	}

	if _, found := common.VariantMap[game.Variant]; !found {
		return fmt.Errorf("Unknown variant for %+v", game)
	}

	if _, found := common.AllocationMethodMap[game.AllocationMethod]; !found {
		return fmt.Errorf("Unknown allocation method for %+v", game)
	}

	member := &Member{
		UserId:           kol.Id(c.Principal()),
		PreferredNations: state.Members[0].PreferredNations,
	}
	return c.Transact(func(c common.WSContext) error {
		if err := c.DB().Set(game); err != nil {
			return err
		}
		member.GameId = game.Id
		return c.DB().Set(member)
	})
}
Beispiel #10
0
func SubscribeMine(c common.WSContext) error {
	if c.Principal() == "" {
		return websocket.JSON.Send(c.Conn(), gosubs.Message{
			Type: gosubs.FetchType,
			Object: &gosubs.Object{
				URI: c.Match()[0],
			},
		})
	}
	s := c.Pack().New(c.Match()[0])
	s.Query = s.DB().Query().Where(kol.Equals{"UserId", kol.Id(c.Principal())})
	s.Call = func(i interface{}, op string) (err error) {
		members := i.([]*Member)
		var ep time.Duration
		ep, err = epoch.Get(c.DB())
		if err != nil {
			return
		}
		states := GameStates{}
		for _, member := range members {
			if op == gosubs.DeleteType {
				states = append(states, GameState{
					Game:    &Game{Id: member.GameId},
					Members: []MemberState{MemberState{Member: member}},
				})
			} else {
				game := &Game{Id: member.GameId}
				if err = s.DB().Get(game); err != nil {
					return
				}
				var gameMembers Members
				if gameMembers, err = game.Members(c.DB()); err != nil {
					return
				}
				var state GameState
				if state, err = game.ToState(c.DB(), gameMembers, member); err != nil {
					return
				}
				states = append(states, state)
			}
		}
		if op == gosubs.FetchType || len(states) > 0 {
			states = states.SortAndLimit(func(a, b GameState) bool {
				urgencyA := time.Hour * 24 * 365
				urgencyB := time.Hour * 24 * 365
				switch a.State {
				case common.GameStateStarted:
					_, phase, err := a.Game.Phase(c.DB(), 0)
					if err == nil {
						urgencyA = phase.Deadline - ep
					}
				case common.GameStateCreated:
					urgencyA -= 1
				}
				switch b.State {
				case common.GameStateStarted:
					_, phase, err := b.Game.Phase(c.DB(), 0)
					if err == nil {
						urgencyB = phase.Deadline - ep
					}
				case common.GameStateCreated:
					urgencyB -= 1
				}
				if urgencyA != urgencyB {
					return urgencyA < urgencyB
				}
				return a.CreatedAt.Before(b.CreatedAt)
			}, 1024*16)
			return s.Send(states, op)
		}
		return nil
	}
	return s.Subscribe(&Member{})
}
Beispiel #11
0
func DeleteMember(c common.WSContext) error {
	return c.Transact(func(c common.WSContext) error {
		decodedId, err := kol.DecodeId(c.Match()[1])
		if err != nil {
			return err
		}
		game := &Game{Id: decodedId}
		if err := c.DB().Get(game); err != nil {
			return fmt.Errorf("Game not found: %v", err)
		}
		if game.State != common.GameStateCreated {
			return fmt.Errorf("%+v already started", game)
		}
		member := Member{}
		if _, err := c.DB().Query().Where(kol.And{kol.Equals{"GameId", decodedId}, kol.Equals{"UserId", kol.Id(c.Principal())}}).First(&member); err != nil {
			return err
		}
		if err := c.DB().Del(&member); err != nil {
			return err
		}
		left, err := game.Members(c.DB())
		if err != nil {
			return err
		}
		if len(left) == 0 {
			if err := c.DB().Del(game); err != nil {
				return err
			}
		}
		return nil
	})
}
Beispiel #12
0
func (self *Game) Member(d *kol.DB, email string) (result *Member, err error) {
	var member Member
	var found bool
	if found, err = d.Query().Where(kol.And{kol.Equals{"GameId", self.Id}, kol.Equals{"UserId", kol.Id(email)}}).First(&member); found && err == nil {
		result = &member
	}
	return
}