From 79bc3d28df18c0d36de1337becfdb28284989431 Mon Sep 17 00:00:00 2001
From: Frederick Muriuki Muriithi
Date: Mon, 23 Jan 2023 14:38:55 +0300
Subject: oauth2: create group

Enable creation of a new group.
---
 wqflask/wqflask/oauth2/routes.py                   | 74 +++++++++++++++++--
 wqflask/wqflask/static/new/css/mytooltip.css       | 16 +++++
 .../templates/oauth2/group_join_or_create.html     | 83 ++++++++++++++++++++++
 wqflask/wqflask/templates/oauth2/view-user.html    | 42 +++--------
 4 files changed, 175 insertions(+), 40 deletions(-)
 create mode 100644 wqflask/wqflask/static/new/css/mytooltip.css
 create mode 100644 wqflask/wqflask/templates/oauth2/group_join_or_create.html

diff --git a/wqflask/wqflask/oauth2/routes.py b/wqflask/wqflask/oauth2/routes.py
index 2f4d4492..33282dc1 100644
--- a/wqflask/wqflask/oauth2/routes.py
+++ b/wqflask/wqflask/oauth2/routes.py
@@ -1,5 +1,6 @@
 """Routes for the OAuth2 auth system in GN3"""
 import requests
+from typing import Optional
 from urllib.parse import urljoin
 
 from pymonad.maybe import Just, Maybe, Nothing
@@ -15,6 +16,9 @@ from .checks import require_oauth2, user_logged_in
 oauth2 = Blueprint("oauth2", __name__)
 SCOPE = "profile group role resource register-client"
 
+def __raise_unimplemented__():
+    raise Exception("NOT IMPLEMENTED")
+
 def get_endpoint(uri_path: str) -> Maybe:
     token = session.get("oauth2_token", False)
     if token and not bool(session.get("user_details", False)):
@@ -36,6 +40,10 @@ def get_endpoint(uri_path: str) -> Maybe:
 
     return Nothing
 
+def __user_details__():
+    return session.get("user_details", False) or get_endpoint(
+        "oauth2/user").maybe(False, __id__)
+
 def oauth2_get(uri_path: str) -> Either:
     token = session.get("oauth2_token")
     config = app.config
@@ -49,6 +57,18 @@ def oauth2_get(uri_path: str) -> Either:
 
     return Left(resp.json())
 
+def oauth2_post(uri_path: str, data: dict) -> Either:
+    token = session.get("oauth2_token")
+    config = app.config
+    client = OAuth2Session(
+        config["OAUTH2_CLIENT_ID"], config["OAUTH2_CLIENT_SECRET"],
+        token=token, scope=SCOPE)
+    resp = client.post(urljoin(config["GN_SERVER_URL"], uri_path), data=data)
+    if resp.status_code == 200:
+        return Right(resp.json())
+
+    return Left(resp.json())
+
 @oauth2.route("/login", methods=["GET", "POST"])
 def login():
     """Route to allow users to sign up."""
@@ -139,8 +159,7 @@ def register_client():
 @require_oauth2
 def user_profile():
     __id__ = lambda the_val: the_val
-    user_details = session.get("user_details", False) or get_endpoint(
-        "oauth2/user").maybe(False, __id__)
+    user_details = __user_details__()
     config = app.config
     client = OAuth2Session(
         config["OAUTH2_CLIENT_ID"], config["OAUTH2_CLIENT_SECRET"],
@@ -148,10 +167,8 @@ def user_profile():
 
     roles = oauth2_get("oauth2/user-roles").either(lambda x: "Error", lambda x: x)
     resources = []
-    groups = [] if user_details.get("group") else oauth2_get("oauth2/groups").either(
-        lambda x: "Error", lambda x: x)
     return render_template(
-        "oauth2/view-user.html", user_details=user_details, groups=groups,
+        "oauth2/view-user.html", user_details=user_details,
         roles=roles, resources=resources)
 
 @oauth2.route("/request-add-to-group", methods=["POST"])
@@ -159,7 +176,52 @@ def user_profile():
 def request_add_to_group():
     return "WOULD SEND MESSAGE TO HAVE YOU ADDED TO GROUP..."
 
+def __handle_error__(redirect_uri: Optional[str] = None, **kwargs):
+    def __handler__(error):
+        print(f"ERROR: {error}")
+        msg = error.get(
+            "error_message", error.get("error_description", "undefined error"))
+        flash(f"{error['error']}: {msg}.",
+              "alert-danger")
+        if "response_handlers" in kwargs:
+            for handler in kwargs["response_handlers"]:
+                handler(response)
+        if redirect:
+            return redirect(url_for(redirect_uri, **kwargs))
+
+    return __handler__
+
+def __handle_success__(
+        success_msg: str, redirect_uri: Optional[str] = None, **kwargs):
+    def __handler__(response):
+        flash(f"Success: {success_msg}.", "alert-success")
+        if "response_handlers" in kwargs:
+            for handler in kwargs["response_handlers"]:
+                handler(response)
+        if redirect:
+            return redirect(url_for(redirect_uri, **kwargs))
+
+    return __handler__
+
 @oauth2.route("/create-group", methods=["POST"])
 @require_oauth2
 def create_group():
-    return "WOULD CREATE A NEW GROUP..."
+    def __setup_group__(response):
+        session["user_details"]["group"] = response
+
+    resp = oauth2_post("oauth2/create-group", data=dict(request.form))
+    return resp.either(
+        __handle_error__("oauth2.group_join_or_create"),
+        __handle_success__(
+            "Created group", "oauth2.user_profile",
+            response_handlers=__setup_group__))
+
+@oauth2.route("/group-join-or-create", methods=["GET"])
+def group_join_or_create():
+    user_details = __user_details__()
+    if bool(user_details["group"]):
+        flash("You are already a member of a group.", "alert info.")
+        return redirect(url_for("oauth2.user_profile"))
+    groups = oauth2_get("oauth2/groups").either(
+        lambda x: __raise_unimplemented__(), lambda x: x)
+    return render_template("oauth2/group_join_or_create.html", groups=groups)
diff --git a/wqflask/wqflask/static/new/css/mytooltip.css b/wqflask/wqflask/static/new/css/mytooltip.css
new file mode 100644
index 00000000..bc44c488
--- /dev/null
+++ b/wqflask/wqflask/static/new/css/mytooltip.css
@@ -0,0 +1,16 @@
+.mytooltiptext {
+    visibility: hidden;
+    width: inherit;
+    background-color: #E5E5AF;
+    color: #595959;
+    text-align: left;
+    padding: 5px 0;
+    border-radius: 6px;
+
+    position: absolute;
+    z-index: 1;
+}
+
+.mytooltip:hover .mytooltiptext {
+    visibility: visible;
+}
diff --git a/wqflask/wqflask/templates/oauth2/group_join_or_create.html b/wqflask/wqflask/templates/oauth2/group_join_or_create.html
new file mode 100644
index 00000000..d0a10e1b
--- /dev/null
+++ b/wqflask/wqflask/templates/oauth2/group_join_or_create.html
@@ -0,0 +1,83 @@
+{%extends "base.html"%}
+{%block title%}Join or Create Group{%endblock%}
+
+{%block css%}
+<link rel="stylesheet" type="text/css" href="/static/new/css/mytooltip.css" />
+{%endblock%}
+{%block content%}
+<div class="container" style="min-width: 1250px;">
+  <h3>Join or Create Group</h3>
+
+  {{flash_me()}}
+
+  <p>You can</p>
+
+  {%if groups | length > 0 %}
+  <div  class="explainer">
+    <p>
+    For most users, this is the preffered choice. You request access to an
+    existing group, and the group leader will chose whether or not to add you to
+    their group.</p>
+
+    <p>You can only be a member of a single group.</p>
+  </div>
+
+  <form action="{{url_for('oauth2.request_add_to_group')}}"
+	method="POST">
+    <legend>Request to be added to group</legend>
+    <div class="form-group">
+      <label class="control-label" for="group">Group</label>
+      <select class="form-control" id="group" required="required">
+	<option value="">Select a group</option>
+	{%for group in groups%}
+	<option value="{{group.group_id}}">{{group.group_name}}</option>
+	{%endfor%}
+      </select>
+    </div>
+    <div class="form-group">
+      <input type="submit" value="Request Access" class="btn btn-primary" />
+    </div>
+  </form>
+
+  <p>or</p>
+  {%else%}
+  <p>
+    <span class="glyphicon glyphicon-warning-sign text-warning"></span>
+    &nbsp;
+    <span class="text-warning">There an currently no groups to join.</span>
+  </p>
+  {%endif%}
+
+  <div  class="explainer">
+  <p>
+    Creating a new group automatically makes you that group's administrator.
+  </p>
+
+  <p>You can only be a member of a single group.</p>
+  </div>
+
+  <form action="{{url_for('oauth2.create_group')}}"
+	method="POST">
+    <legend>Create a new group</legend>
+    <div class="form-group mytooltip">
+      <label class="control-label" for="group_name">Group Name</label>
+      <input type="text" class="form-control" id="group_name"
+	     name="group_name"required="required" />
+      <span class="mytooltiptext">
+	Name of the group.
+      </span>
+    </div>
+    <div class="form-group mytooltip">
+      <label class="control-label" for="group_desc">Group Description</label>
+      <textarea class="form-control" id="group_description"
+		name="group_description"></textarea>
+      <span class="mytooltiptext">
+	A description to help identify the purpose/goal of the group
+      </span>
+    </div>
+    <div class="form-group">
+      <input type="submit" value="Create Group" class="btn btn-primary" />
+    </div>
+  </form>
+</div>
+{%endblock%}
diff --git a/wqflask/wqflask/templates/oauth2/view-user.html b/wqflask/wqflask/templates/oauth2/view-user.html
index 2d5270d9..a617c66e 100644
--- a/wqflask/wqflask/templates/oauth2/view-user.html
+++ b/wqflask/wqflask/templates/oauth2/view-user.html
@@ -4,6 +4,8 @@
 <div class="container" style="min-width: 1250px;">
   <h3>View User</h3>
 
+  {{flash_me()}}
+
   <div class="container-fluid">
     <div class="row">
       <div class="panel panel-primary col-md-3">
@@ -13,7 +15,7 @@
 	  <p><strong>Name</strong>: {{user_details.name}}</p>
 	  <p><strong>E-Mail</strong>: {{user_details.email}}</p>
 	  {%if user_details.group%}
-	  <p><strong>Group</strong>:{{user_details.group}}</p>
+	  <p><strong>Group</strong>:{{user_details.group.group_name}}</p>
 	  {%else%}
 	  <p>
 	    <span class="glyphicon glyphicon-warning-sign text-warning"></span>
@@ -21,39 +23,11 @@
 	    <span class="text-warning">User is not a member of a group.</span>
 	  </p>
 
-	  <p>You can</p>
-
-	  <form action="{{url_for('oauth2.request_add_to_group')}}"
-		method="POST">
-	    <legend>Request to be added to group</legend>
-	    <div class="form-group">
-	      <label class="control-label" for="group">Group</label>
-	      <select class="form-control" id="group" required="required">
-		<option value="">Select a group</option>
-		{%for group in groups%}
-		<option value="{{group.group_id}}">{{group.group_name}}</option>
-		{%endfor%}
-	      </select>
-	    </div>
-	    <div class="form-group">
-	      <input type="submit" value="Request Access" class="btn btn-primary" />
-	    </div>
-	  </form>
-
-	  <p>or</p>
-
-	  <form action="{{url_for('oauth2.create_group')}}"
-		method="POST">
-	    <legend>Create a new group</legend>
-	    <div class="form-group">
-	      <label class="control-label" for="group_name">Group Name</label>
-	      <input type="text" class="form-control" id="group_name" name="group_name"
-		     required="required" />
-	    </div>
-	    <div class="form-group">
-	      <input type="submit" value="Create Group" class="btn btn-primary" />
-	    </div>
-	  </form>
+	  <p><a href="{{url_for('oauth2.group_join_or_create')}}"
+		class="btn btn-primary"
+		title="Join an existing group, or create your own group">
+	      Join or Create group
+	  </a></p>
 	  {%endif%}
 	  {%else%}
 	  <p class="text-warning">No details found.</p>
-- 
cgit v1.2.3