Accept invitations.
This commit is contained in:
parent
f99a47cb2c
commit
9f8e7ee95f
7 changed files with 121 additions and 85 deletions
5
problems/misc/survey/problem.json
Normal file
5
problems/misc/survey/problem.json
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"title": "Survey",
|
||||||
|
"description": "Take our survey.",
|
||||||
|
|
||||||
|
}
|
|
@ -30,6 +30,16 @@ class Users(db.Model):
|
||||||
self.admin = False
|
self.admin = False
|
||||||
self.registertime = int(time.time())
|
self.registertime = int(time.time())
|
||||||
|
|
||||||
|
def get_invitations(self):
|
||||||
|
invitations = db.session.query(TeamInvitations).filter_by(rtype=0, toid=self.uid).all()
|
||||||
|
result = [ ]
|
||||||
|
for inv in invitations:
|
||||||
|
team = db.session.query(Teams).filter_by(tid=inv.frid).first()
|
||||||
|
result.append({
|
||||||
|
"team": team.teamname
|
||||||
|
})
|
||||||
|
return result
|
||||||
|
|
||||||
class Teams(db.Model):
|
class Teams(db.Model):
|
||||||
tid = db.Column(db.Integer, primary_key=True)
|
tid = db.Column(db.Integer, primary_key=True)
|
||||||
teamname = db.Column(db.String(64), unique=True)
|
teamname = db.Column(db.String(64), unique=True)
|
||||||
|
|
|
@ -162,6 +162,34 @@ def team_invite_request():
|
||||||
|
|
||||||
return { "success": 1, "message": "Success!" }
|
return { "success": 1, "message": "Success!" }
|
||||||
|
|
||||||
|
@blueprint.route("/invite/accept", methods=["POST"])
|
||||||
|
@api_wrapper
|
||||||
|
def team_accept_invite():
|
||||||
|
params = utils.flat_multi(request.form)
|
||||||
|
_user = user.get_user().first()
|
||||||
|
if user.in_team(_user):
|
||||||
|
raise WebException("You're already in a team!")
|
||||||
|
|
||||||
|
tid = params.get("tid")
|
||||||
|
_team = get_team(tid=tid).first()
|
||||||
|
if _team is None:
|
||||||
|
raise WebException("Team not found.")
|
||||||
|
|
||||||
|
invitation = TeamInvitations.query.filter_by(rtype=0, frid=tid, toid=_user.uid).first()
|
||||||
|
if invitation is None:
|
||||||
|
raise WebException("Invitation doesn't exist.")
|
||||||
|
|
||||||
|
with app.app_context():
|
||||||
|
_user = Users.query.filter_by(uid=_user.uid).first()
|
||||||
|
_user.tid = tid
|
||||||
|
db.session.delete(invitation)
|
||||||
|
invitation2 = TeamInvitations.query.filter_by(rtype=1, frid=_user.uid, toid=tid).first()
|
||||||
|
if invitation2 is not None:
|
||||||
|
db.session.delete(invitation2)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
return { "success": 1, "message": "Success!" }
|
||||||
|
|
||||||
@blueprint.route("/info", methods=["GET"])
|
@blueprint.route("/info", methods=["GET"])
|
||||||
@api_wrapper
|
@api_wrapper
|
||||||
def team_info():
|
def team_info():
|
||||||
|
@ -196,6 +224,9 @@ def team_info():
|
||||||
if logged_in:
|
if logged_in:
|
||||||
teamdata["invited"] = team.get_pending_invitations(toid=_user.uid) is not None
|
teamdata["invited"] = team.get_pending_invitations(toid=_user.uid) is not None
|
||||||
teamdata["requested"] = team.get_invitation_requests(frid=_user.uid) is not None
|
teamdata["requested"] = team.get_invitation_requests(frid=_user.uid) is not None
|
||||||
|
else:
|
||||||
|
if logged_in:
|
||||||
|
teamdata["invitations"] = _user.get_invitations()
|
||||||
return { "success": 1, "team": teamdata }
|
return { "success": 1, "team": teamdata }
|
||||||
|
|
||||||
##################
|
##################
|
||||||
|
|
|
@ -166,6 +166,9 @@ def user_info():
|
||||||
userdata["email"] = user.email
|
userdata["email"] = user.email
|
||||||
if user_in_team:
|
if user_in_team:
|
||||||
userdata["team"] = team.get_team_info(tid=user.tid)
|
userdata["team"] = team.get_team_info(tid=user.tid)
|
||||||
|
if me and not(user_in_team):
|
||||||
|
invitations = user.get_invitations()
|
||||||
|
userdata["invitations"] = invitations
|
||||||
return { "success": 1, "user": userdata }
|
return { "success": 1, "user": userdata }
|
||||||
|
|
||||||
##################
|
##################
|
||||||
|
|
|
@ -317,7 +317,6 @@ var login_form = function() {
|
||||||
// team page
|
// team page
|
||||||
|
|
||||||
var create_team = function() {
|
var create_team = function() {
|
||||||
<<<<<<< HEAD
|
|
||||||
var input = "#create_team input";
|
var input = "#create_team input";
|
||||||
var data = $("#create_team").serializeObject();
|
var data = $("#create_team").serializeObject();
|
||||||
$(input).attr("disabled", "disabled");
|
$(input).attr("disabled", "disabled");
|
||||||
|
@ -353,43 +352,6 @@ var add_member = function() {
|
||||||
$(input).removeAttr("disabled");
|
$(input).removeAttr("disabled");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
=======
|
|
||||||
var input = "#create_team input";
|
|
||||||
var data = $("#create_team").serializeObject();
|
|
||||||
$(input).attr("disabled", "disabled");
|
|
||||||
api_call("POST", "/api/team/create", data, function(result) {
|
|
||||||
if (result["success"] == 1) {
|
|
||||||
location.reload(true);
|
|
||||||
} else {
|
|
||||||
display_message("create_team_msg", "danger", result["message"], function() {
|
|
||||||
$(input).removeAttr("disabled");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, function(jqXHR, status, error) {
|
|
||||||
var result = jqXHR["responseText"];
|
|
||||||
display_message("create_team_msg", "danger", "Error " + jqXHR["status"] + ": " + result["message"], function() {
|
|
||||||
$(input).removeAttr("disabled");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var add_member = function() {
|
|
||||||
var input = "#add_member input";
|
|
||||||
var data = $("#add_member").serializeObject();
|
|
||||||
$(input).attr("disabled", "disabled");
|
|
||||||
api_call("POST", "/api/team/invite", data, function(result) {
|
|
||||||
if (result["success"] == 1) {
|
|
||||||
location.reload(true);
|
|
||||||
} else {
|
|
||||||
$(input).removeAttr("disabled");
|
|
||||||
}
|
|
||||||
}, function(jqXHR, status, error) {
|
|
||||||
var result = JSON.parse(jqXHR["responseText"]);
|
|
||||||
display_message("create_team_msg", "danger", "Error " + jqXHR["status"] + ": " + result["message"], function() {
|
|
||||||
$(input).removeAttr("disabled");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
>>>>>>> d6564d17efae214a3284d1afe243952d90d0b752
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var rescind_invitation = function(uid) {
|
var rescind_invitation = function(uid) {
|
||||||
|
@ -411,3 +373,12 @@ var request_invitation = function(tid) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var accept_invitation = function(tid) {
|
||||||
|
var data = { "tid": tid };
|
||||||
|
api_call("POST", "/api/team/invite/accept", data, function(result) {
|
||||||
|
if (result["success"] == 1) {
|
||||||
|
location.reload(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
|
@ -59,6 +59,7 @@
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body" ng-show="user['in_team']!=true">
|
<div class="panel-body" ng-show="user['in_team']!=true">
|
||||||
|
<div class="alert alert-success" ng-show="user['me']==true && user['invitations'].length>0">You have {{ user['invitations'].length }} invitation{{ user['invitations'].length==1 ? "" : "s" }}! <a href="/team">View »</a></div>
|
||||||
<p>{{ user['me']==true ? "You're" : "This user is" }} not a part of a team.</p>
|
<p>{{ user['me']==true ? "You're" : "This user is" }} not a part of a team.</p>
|
||||||
<a href="/team" class="btn btn-primary" ng-show="user['me']==true">Join or create one now »</a>
|
<a href="/team" class="btn btn-primary" ng-show="user['me']==true">Join or create one now »</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -41,7 +41,8 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="list-group">
|
<div class="list-group">
|
||||||
<div class="list-group-item" ng-repeat="member in team['members']">
|
<div class="list-group-item" ng-repeat="member in team['members']">
|
||||||
<h4 class="list-group-item-heading">{{ member['name'] }}</h4>
|
<h4 class="list-group-item-heading" style="display:inline-block;">{{ member['name'] }}</h4>
|
||||||
|
<div class="label label-info" ng-show="member['captain']==true">Owner</div>
|
||||||
<p class="list-group-item-text">@{{ member['username'] }}</p>
|
<p class="list-group-item-text">@{{ member['username'] }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -102,59 +103,73 @@
|
||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
<h1>Team</h1>
|
<h1>Team</h1>
|
||||||
</div>
|
</div>
|
||||||
<p>To participate in EasyCTF, you must be on a <b>team</b>. If you'd like to go solo, just create a team by yourself. Read about team eligibility in the <a href="/rules">rules</a>.</p>
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="page-header">
|
||||||
|
<h3>New Team</h3>
|
||||||
|
</div>
|
||||||
|
<p>To participate in EasyCTF, you must be on a <b>team</b>. If you'd like to go solo, just create a team by yourself. Read about team eligibility in the <a href="/rules">rules</a>.</p>
|
||||||
|
|
||||||
<form class="form-horizontal" onsubmit="create_team(); return false;" id="create_team">
|
<form class="form-horizontal" onsubmit="create_team(); return false;" id="create_team">
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<div id="create_team_msg"></div>
|
<div id="create_team_msg"></div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<fieldset class="container-fluid">
|
<fieldset class="container-fluid">
|
||||||
<div class="col-md-6 col-md-offset-3 col-sm-10 col-sm-offset-1">
|
<div class="col-md-12">
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<h2 class="panel-title">Create a Team</h2>
|
<h2 class="panel-title">Create a Team</h2>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<form class="form-horizontal" onsubmit="login_form(); return false;" id="login_form">
|
<form class="form-horizontal" onsubmit="login_form(); return false;" id="login_form">
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<div id="login_msg"></div>
|
<div id="login_msg"></div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<fieldset class="container-fluid">
|
<fieldset class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-12 form-group">
|
<div class="col-sm-12 form-group">
|
||||||
<label class="col-sm-12" for="teamname"><small>Team Name</small></label>
|
<label class="col-sm-12" for="teamname"><small>Team Name</small></label>
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<input class="form-control" type="text" required name="teamname" id="teamname" placeholder="Create a team name..." autocomplete="off" />
|
<input class="form-control" type="text" required name="teamname" id="teamname" placeholder="Create a team name..." autocomplete="off" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="row">
|
||||||
</div>
|
<div class="col-sm-12 form-group">
|
||||||
<div class="row">
|
<label class="col-sm-12" for="school"><small>School Name</small></label>
|
||||||
<div class="col-sm-12 form-group">
|
<div class="col-sm-12">
|
||||||
<label class="col-sm-12" for="school"><small>School Name</small></label>
|
<input class="form-control" type="text" required name="school" id="school" placeholder="School Name" autocomplete="off" />
|
||||||
<div class="col-sm-12">
|
</div>
|
||||||
<input class="form-control" type="text" required name="school" id="school" placeholder="School Name" autocomplete="off" />
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="row">
|
||||||
</div>
|
<div class="col-sm-12 form-group">
|
||||||
<div class="row">
|
<center>
|
||||||
<div class="col-sm-12 form-group">
|
<input type="submit" class="btn btn-success btn-lg" value="Create Team" />
|
||||||
<center>
|
</center>
|
||||||
<input type="submit" class="btn btn-success btn-lg" value="Create Team" />
|
</div>
|
||||||
</center>
|
</div>
|
||||||
</div>
|
</fieldset>
|
||||||
</div>
|
</form>
|
||||||
</fieldset>
|
</div>
|
||||||
</form>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="page-header">
|
||||||
|
<h3>Invitations</h3>
|
||||||
|
</div>
|
||||||
|
<p ng-show="team['invitations'].length==0">You need an invitation to join another team. If you'd like to request to be a member of their team, go to their team page and click the Request button.</p>
|
||||||
|
<div ng-show="team['invitations'].length>0" class="list-group">
|
||||||
|
<div class="list-group-item" ng-repeat="invitation in team['invitations']">
|
||||||
|
<a href="/team/{{ invitation['team'] }}">{{ invitation['team'] }}</a>
|
||||||
|
<a href="javascript:accept_invitation();" class="badge">Accept »</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</div>
|
||||||
</form>
|
|
||||||
|
|
||||||
<div class="page-header">
|
|
||||||
<h3>Invitations</h3>
|
|
||||||
</div>
|
</div>
|
||||||
<p>You need an invitation to join another team. If you'd like to request to be a member of their team, go to their team page and click the Request button.</p>
|
|
||||||
</div>
|
</div>
|
||||||
<div ng-show="!(team['tid'] >= 0) && config.navbar['logged_in']!=true">
|
<div ng-show="!(team['tid'] >= 0) && config.navbar['logged_in']!=true">
|
||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
|
|
Loading…
Reference in a new issue