예제 #1
0
파일: grant.py 프로젝트: ogonbat/click2call
    def post(self):
        """POST action to authorize the Client Application.
        To authorize will be send a POST with 'grant' parameter set to true, to deny 'parameter' set to false."""
        grant = self.get_argument("grant")
        client_id = self.get_argument("client_id")
        response_type = self.get_argument("response_type")
        redirect_uri = self.get_argument("redirect_uri")
        scope = self.get_argument("scope")
        # the client send correct paramenters, we need to check if the client id exist and we
        # create the relation between the user-agent and the client
        if grant == "true":
            try:
                #check if the client exist
                client = Client()
                exist = client.get(client_id=client_id)
                if exist['redirect_uri'] != redirect_uri:
                    #have an error, return a 403
                    raise tornado.web.HTTPError(403,"redirect uri problem")
            except ObjectDoesNotExist, e:
                raise tornado.web.HTTPError(403,"the client id not correspond to any Client")

            grant = Grant()
            try:
                #we accept the grant for the user
                grant.is_already_authorized(client_id,self.get_current_user())
                grant.update(client_id,self.get_current_user())
            except ObjectDoesNotExist, e:
                grant.add(client_id,self.get_current_user())
예제 #2
0
파일: auth.py 프로젝트: ogonbat/click2call
    def get(self):
        """This Method check if the Application Client exist, if yes redirect to the login page.
        In Case something goes wrong the Handler return a 400 status code if the Client Id does not exist and 400 if the parameters send are not correct."""
        client_id = self.get_argument("client_id")
        response_type = self.get_argument("response_type")
        redirect_uri = self.get_argument("redirect_uri")
        scope = self.get_argument("scope")

        # before check if the client pass client_id, redirect_url and response_type
        # we accept only token "Implicit Grant Flow"
        # if all is ok we need to check if the client_id and the redirect_uri are correct
        # if not we return a 403 to the client
        if response_type in ("token","code"):
            try:
                client_check = Client()
                exist = client_check.get(client_id=client_id)
                #check the redirect_uri parameter
                if exist['redirect_uri'] != redirect_uri:
                    #have an error, return a 403
                    raise tornado.web.HTTPError(403,"redirect uri problem")
                # redirect to login page
                self.redirect(("/auth/login?client_id=%s&response_type=%s&redirect_uri=%s&scope=%s")%(client_id,
                                                                                                      response_type,
                                                                                                      urllib.quote_plus(redirect_uri),
                                                                                                      scope))
            except ObjectDoesNotExist, e:
                raise tornado.web.HTTPError(403)
def generate_fakes():
	Author.generate_fake()
	BookDetails.generate_fake()
	BookInventory.generate_fake()
	Client.generate_fake()
	Person.generate_fake()
	Volunteer.generate_fake()
	Donor.generate_fake()
예제 #4
0
	def test_client_bad_init(self):
		c = Client('Alice', '*****@*****.**', '+79099946885')
		c.password = '******'
		db.session.add(c)
		flag = False
		try:
			db.session.commit()
		except:
			flag = True
		self.assertTrue(flag)
예제 #5
0
	def test_client_unique(self):
		c1 = Client('Alice', '*****@*****.**', '+79099946885')
		c2 = Client('Alice', '*****@*****.**', '+79099946885')
		c1.password = '******'
		c2.password = '******'
		db.session.add(c1)
		db.session.add(c2)
		flag = False
		try:
			db.session.commit()
		except:
			flag = True
		self.assertTrue(flag)
예제 #6
0
파일: grant.py 프로젝트: ogonbat/click2call
 def get(self):
     """This is the form where the user accept or denied the access to the Application Client.
     In this test the form is not returned."""
     client_id = self.get_argument("client_id")
     response_type = self.get_argument("response_type")
     redirect_uri = self.get_argument("redirect_uri")
     scope = self.get_argument("scope")
     try:
         #check if the client exist
         client = Client()
         exist = client.get(client_id=client_id)
         if exist['redirect_uri'] != redirect_uri:
             #have an error, return a 403
             raise tornado.web.HTTPError(403,"redirect uri problem")
     except ObjectDoesNotExist, e:
         raise tornado.web.HTTPError(403,"the client id not correspond to any Client")
예제 #7
0
파일: token.py 프로젝트: ogonbat/click2call
    def get(self):
        """Get method.
        return the token and the refresh if all the parameters passed are correct."""
        code = self.get_argument("code")
        client_id = self.get_argument("client_id")
        client_secret = self.get_argument("client_secret")
        redirect_uri = self.get_argument("redirect_uri")
        grant_type = self.get_argument("grant_type")

        try:
            client_check = Client()
            exist = client_check.get(client_id=client_id)
            if exist["redirect_uri"] != redirect_uri:
                # have an error, return a 403
                raise tornado.web.HTTPError(403, "redirect uri problem")
            # check the redirect_uri parameter
            token_result = client_check.authenticate(client_id, client_secret, code)

            self.redirect(
                (redirect_uri + "?access_token=%s&expires_in=%s&token_type=Bearer") % (token_result["token"], 3600)
            )
        except ObjectDoesNotExist, e:
            raise tornado.web.HTTPError(403)
예제 #8
0
def new_client() -> Response:
    client: Client = Client.from_json(request.json)
    db.session.add(client)
    db.session.commit()
    return jsonify(client.to_json()), 201
예제 #9
0
파일: signals.py 프로젝트: ojengwa/apipanda
def add_to_org(sender, **kwargs):
    org = sender.objects.last()
    user = org.creator

    member, created = OrganisationMember.objects.get_or_create(org=org,
                                                               member=user)

    if created:
        tld = tldextract.extract(org.url)

        client = Client()
        client.name = org.name
        client.organisation = org
        client.schema_name = org.slug
        client.paid_until = datetime.now() + timedelta(days=90)
        try:
            client.domain_url = tld.domain
            client.save()
        except KeyError:
            try:
                client.domain_url = tld.domain + '-' + tld.subdomain
                client.save()
            except KeyError:
                client.domain_url = org.slug
                client.save()
예제 #10
0
파일: server.py 프로젝트: doanguyen/app
def fake_data():
    LOG.d("create fake data")
    # Remove db if exist
    if os.path.exists("db.sqlite"):
        LOG.d("remove existing db file")
        os.remove("db.sqlite")

    # Create all tables
    db.create_all()

    # Create a user
    user = User.create(
        email="*****@*****.**",
        name="John Wick",
        password="******",
        activated=True,
        is_admin=True,
    )
    db.session.commit()

    # Create a subscription for user
    Subscription.create(
        user_id=user.id,
        cancel_url="https://checkout.paddle.com/subscription/cancel?user=1234",
        update_url="https://checkout.paddle.com/subscription/update?user=1234",
        subscription_id="123",
        event_time=arrow.now(),
        next_bill_date=arrow.now().shift(days=10).date(),
        plan=PlanEnum.monthly,
    )
    db.session.commit()

    api_key = ApiKey.create(user_id=user.id, name="Chrome")
    api_key.code = "code"

    GenEmail.create_new(user.id, "e1@")
    GenEmail.create_new(user.id, "e2@")
    GenEmail.create_new(user.id, "e3@")

    CustomDomain.create(user_id=user.id, domain="ab.cd", verified=True)
    CustomDomain.create(
        user_id=user.id, domain="very-long-domain.com.net.org", verified=True
    )
    db.session.commit()

    # Create a client
    client1 = Client.create_new(name="Demo", user_id=user.id)
    client1.oauth_client_id = "client-id"
    client1.oauth_client_secret = "client-secret"
    client1.published = True
    db.session.commit()

    RedirectUri.create(client_id=client1.id, uri="https://ab.com")

    client2 = Client.create_new(name="Demo 2", user_id=user.id)
    client2.oauth_client_id = "client-id2"
    client2.oauth_client_secret = "client-secret2"
    client2.published = True
    db.session.commit()

    db.session.commit()
예제 #11
0
def setting():
    form = SettingForm()
    promo_form = PromoCodeForm()
    change_email_form = ChangeEmailForm()

    email_change = EmailChange.get_by(user_id=current_user.id)
    if email_change:
        pending_email = email_change.new_email
    else:
        pending_email = None

    if request.method == "POST":
        if request.form.get("form-name") == "update-email":
            if change_email_form.validate():
                # whether user can proceed with the email update
                new_email_valid = True
                if (change_email_form.email.data.lower().strip() !=
                        current_user.email and not pending_email):
                    new_email = change_email_form.email.data.strip().lower()

                    # check if this email is not already used
                    if personal_email_already_used(new_email) or Alias.get_by(
                            email=new_email):
                        flash(f"Email {new_email} already used", "error")
                        new_email_valid = False
                    elif not email_can_be_used_as_mailbox(new_email):
                        flash(
                            "You cannot use this email address as your personal inbox.",
                            "error",
                        )
                        new_email_valid = False
                    # a pending email change with the same email exists from another user
                    elif EmailChange.get_by(new_email=new_email):
                        other_email_change: EmailChange = EmailChange.get_by(
                            new_email=new_email)
                        LOG.warning(
                            "Another user has a pending %s with the same email address. Current user:%s",
                            other_email_change,
                            current_user,
                        )

                        if other_email_change.is_expired():
                            LOG.d("delete the expired email change %s",
                                  other_email_change)
                            EmailChange.delete(other_email_change.id)
                            db.session.commit()
                        else:
                            flash(
                                "You cannot use this email address as your personal inbox.",
                                "error",
                            )
                            new_email_valid = False

                    if new_email_valid:
                        email_change = EmailChange.create(
                            user_id=current_user.id,
                            code=random_string(
                                60),  # todo: make sure the code is unique
                            new_email=new_email,
                        )
                        db.session.commit()
                        send_change_email_confirmation(current_user,
                                                       email_change)
                        flash(
                            "A confirmation email is on the way, please check your inbox",
                            "success",
                        )
                        return redirect(url_for("dashboard.setting"))
        if request.form.get("form-name") == "update-profile":
            if form.validate():
                profile_updated = False
                # update user info
                if form.name.data != current_user.name:
                    current_user.name = form.name.data
                    db.session.commit()
                    profile_updated = True

                if form.profile_picture.data:
                    file_path = random_string(30)
                    file = File.create(user_id=current_user.id, path=file_path)

                    s3.upload_from_bytesio(
                        file_path, BytesIO(form.profile_picture.data.read()))

                    db.session.flush()
                    LOG.d("upload file %s to s3", file)

                    current_user.profile_picture_id = file.id
                    db.session.commit()
                    profile_updated = True

                if profile_updated:
                    flash("Your profile has been updated", "success")
                    return redirect(url_for("dashboard.setting"))

        elif request.form.get("form-name") == "change-password":
            flash(
                "You are going to receive an email containing instructions to change your password",
                "success",
            )
            send_reset_password_email(current_user)
            return redirect(url_for("dashboard.setting"))

        elif request.form.get("form-name") == "notification-preference":
            choose = request.form.get("notification")
            if choose == "on":
                current_user.notification = True
            else:
                current_user.notification = False
            db.session.commit()
            flash("Your notification preference has been updated", "success")
            return redirect(url_for("dashboard.setting"))

        elif request.form.get("form-name") == "delete-account":
            LOG.warning("Delete account %s", current_user)
            User.delete(current_user.id)
            db.session.commit()
            flash("Your account has been deleted", "success")
            logout_user()
            return redirect(url_for("auth.register"))

        elif request.form.get("form-name") == "change-alias-generator":
            scheme = int(request.form.get("alias-generator-scheme"))
            if AliasGeneratorEnum.has_value(scheme):
                current_user.alias_generator = scheme
                db.session.commit()
            flash("Your preference has been updated", "success")
            return redirect(url_for("dashboard.setting"))

        elif request.form.get(
                "form-name") == "change-random-alias-default-domain":
            default_domain = request.form.get("random-alias-default-domain")

            if default_domain:
                sl_domain: SLDomain = SLDomain.get_by(domain=default_domain)
                if sl_domain:
                    if sl_domain.premium_only and not current_user.is_premium(
                    ):
                        flash("You cannot use this domain", "error")
                        return redirect(url_for("dashboard.setting"))

                    # make sure only default_random_alias_domain_id or default_random_alias_public_domain_id is set
                    current_user.default_random_alias_public_domain_id = sl_domain.id
                    current_user.default_random_alias_domain_id = None
                else:
                    custom_domain = CustomDomain.get_by(domain=default_domain)
                    if custom_domain:
                        # sanity check
                        if (custom_domain.user_id != current_user.id
                                or not custom_domain.verified):
                            LOG.exception("%s cannot use domain %s",
                                          current_user, default_domain)
                        else:
                            # make sure only default_random_alias_domain_id or
                            # default_random_alias_public_domain_id is set
                            current_user.default_random_alias_domain_id = (
                                custom_domain.id)
                            current_user.default_random_alias_public_domain_id = None

            else:
                current_user.default_random_alias_domain_id = None
                current_user.default_random_alias_public_domain_id = None

            db.session.commit()
            flash("Your preference has been updated", "success")
            return redirect(url_for("dashboard.setting"))

        elif request.form.get("form-name") == "change-sender-format":
            sender_format = int(request.form.get("sender-format"))
            if SenderFormatEnum.has_value(sender_format):
                current_user.sender_format = sender_format
                db.session.commit()
                flash("Your sender format preference has been updated",
                      "success")
            db.session.commit()
            return redirect(url_for("dashboard.setting"))

        elif request.form.get("form-name") == "replace-ra":
            choose = request.form.get("replace-ra")
            if choose == "on":
                current_user.replace_reverse_alias = True
            else:
                current_user.replace_reverse_alias = False
            db.session.commit()
            flash("Your preference has been updated", "success")
            return redirect(url_for("dashboard.setting"))

        elif request.form.get("form-name") == "sender-in-ra":
            choose = request.form.get("enable")
            if choose == "on":
                current_user.include_sender_in_reverse_alias = True
            else:
                current_user.include_sender_in_reverse_alias = False
            db.session.commit()
            flash("Your preference has been updated", "success")
            return redirect(url_for("dashboard.setting"))

        elif request.form.get("form-name") == "export-data":
            data = {
                "email": current_user.email,
                "name": current_user.name,
                "aliases": [],
                "apps": [],
                "custom_domains": [],
            }

            for alias in Alias.filter_by(
                    user_id=current_user.id).all():  # type: Alias
                data["aliases"].append(
                    dict(email=alias.email, enabled=alias.enabled))

            for custom_domain in CustomDomain.filter_by(
                    user_id=current_user.id).all():
                data["custom_domains"].append(custom_domain.domain)

            for app in Client.filter_by(
                    user_id=current_user.id):  # type: Client
                data["apps"].append(
                    dict(name=app.name,
                         home_url=app.home_url,
                         published=app.published))

            return Response(
                json.dumps(data),
                mimetype="text/json",
                headers={
                    "Content-Disposition": "attachment;filename=data.json"
                },
            )
        elif request.form.get("form-name") == "export-alias":
            data = [["alias", "note", "enabled"]]
            for alias in Alias.filter_by(
                    user_id=current_user.id).all():  # type: Alias
                data.append([alias.email, alias.note, alias.enabled])

            si = StringIO()
            cw = csv.writer(si)
            cw.writerows(data)
            output = make_response(si.getvalue())
            output.headers[
                "Content-Disposition"] = "attachment; filename=aliases.csv"
            output.headers["Content-type"] = "text/csv"
            return output

    manual_sub = ManualSubscription.get_by(user_id=current_user.id)
    coinbase_sub = CoinbaseSubscription.get_by(user_id=current_user.id)

    return render_template(
        "dashboard/setting.html",
        form=form,
        PlanEnum=PlanEnum,
        SenderFormatEnum=SenderFormatEnum,
        promo_form=promo_form,
        change_email_form=change_email_form,
        pending_email=pending_email,
        AliasGeneratorEnum=AliasGeneratorEnum,
        manual_sub=manual_sub,
        coinbase_sub=coinbase_sub,
        FIRST_ALIAS_DOMAIN=FIRST_ALIAS_DOMAIN,
    )
예제 #12
0
 def test_func_get_id(self):
     client = Client(email='email')
     db.session.add(client)
     db.session.commit()
     self.assertEqual(client.id, Client.get_id(client.email))
예제 #13
0
 def test_func_email_is_free(self):
     client = Client(email='email')
     db.session.add(client)
     db.session.commit()
     self.assertFalse(Client.email_is_free('email'))
     self.assertTrue(Client.email_is_free('email1'))
예제 #14
0
def test_authorize_code_id_token_flow(flask_client):
    """make sure the authorize redirects user to correct page for the *ID-Token Code Flow*
    , ie when response_type=id_token,code
    The /authorize endpoint should return an id_token, code and id_token must contain *c_hash*

    The /token endpoint must return a access_token and an id_token

    """

    user = login(flask_client)
    client = Client.create_new("test client", user.id)

    db.session.commit()

    # user allows client on the authorization page
    r = flask_client.post(
        url_for(
            "oauth.authorize",
            client_id=client.oauth_client_id,
            state="teststate",
            redirect_uri="http://localhost",
            response_type="id_token code",  # id_token,code flow
        ),
        data={
            "button": "allow",
            "suggested-email": "[email protected]",
            "suggested-name": "AB CD"
        },
        # user will be redirected to client page, do not allow redirection here
        # to assert the redirect url
        # follow_redirects=True,
    )

    assert r.status_code == 302  # user gets redirected back to client page

    # r.location will have this form http://localhost?state=teststate&code=knuyjepwvg
    o = urlparse(r.location)
    assert o.netloc == "localhost"
    assert not o.fragment
    assert o.query

    # parse the query, should return something like
    # {'state': ['teststate'], 'id_token': ['knuyjepwvg'], 'code': ['longstring']}
    queries = parse_qs(o.query)
    assert len(queries) == 3

    assert queries["state"] == ["teststate"]

    assert len(queries["id_token"]) == 1
    assert len(queries["code"]) == 1

    # id_token must be a valid, correctly signed JWT
    id_token = queries["id_token"][0]
    assert verify_id_token(id_token)

    # make sure jwt has all the necessary fields
    jwt = decode_id_token(id_token)

    # payload should have this format
    # {
    #   'at_hash': 'jLDmoGpuOIHwxeyFEe9SKw',
    #   'aud': 'testclient-sywcpwsyua',
    #   'auth_time': 1565450736,
    #   'avatar_url': None,
    #   'client': 'test client',
    #   'email': '[email protected]',
    #   'email_verified': True,
    #   'exp': 1565454336,
    #   'iat': 1565450736,
    #   'id': 1,
    #   'iss': 'http://localhost',
    #   'name': 'AB CD',
    #   'sub': '1'
    # }
    payload = json.loads(jwt.claims)

    # at_hash MUST be present when the flow is id_token,token
    assert "c_hash" in payload

    assert "aud" in payload
    assert "auth_time" in payload
    assert "avatar_url" in payload
    assert "client" in payload
    assert "email" in payload
    assert "email_verified" in payload
    assert "exp" in payload
    assert "iat" in payload
    assert "id" in payload
    assert "iss" in payload
    assert "name" in payload
    assert "sub" in payload

    # <<< Exchange the code to get access_token >>>
    basic_auth_headers = base64.b64encode(
        f"{client.oauth_client_id}:{client.oauth_client_secret}".encode(
        )).decode("utf-8")

    r = flask_client.post(
        url_for("oauth.token"),
        headers={"Authorization": "Basic " + basic_auth_headers},
        data={
            "grant_type": "authorization_code",
            "code": queries["code"][0]
        },
    )

    # r.json should have this format
    # {
    #   'access_token': 'avmhluhonsouhcwwailydwvhankspptgidoggcbu',
    #   'id_token': 'ab.cd.xy',
    #   'expires_in': 3600,
    #   'scope': '',
    #   'token_type': 'bearer',
    #   'user': {
    #     'avatar_url': None,
    #     'client': 'test client',
    #     'email': '[email protected]',
    #     'email_verified': True,
    #     'id': 1,
    #     'name': 'AB CD'
    #   }
    # }
    assert r.status_code == 200
    assert r.json["access_token"]
    assert r.json["expires_in"] == 3600
    assert not r.json["scope"]
    assert r.json["token_type"] == "Bearer"

    assert r.json["user"] == {
        "avatar_url": None,
        "client": "test client",
        "email": "[email protected]",
        "email_verified": True,
        "id": 1,
        "name": "AB CD",
        "sub": "1",
    }

    # id_token must be returned
    assert r.json["id_token"]

    # id_token must be a valid, correctly signed JWT
    assert verify_id_token(r.json["id_token"])
예제 #15
0
def post_user():
    user = Client(request.form['first_name'], request.form['last_name'])
    db.session.add(user)
    db.session.commit()
    return redirect(url_for('index'))
예제 #16
0
def fake_data():
    LOG.d("create fake data")
    # Remove db if exist
    if os.path.exists("db.sqlite"):
        LOG.d("remove existing db file")
        os.remove("db.sqlite")

    # Create all tables
    db.create_all()

    # Create a user
    user = User.create(
        email="*****@*****.**",
        name="John Wick",
        password="******",
        activated=True,
        is_admin=True,
        enable_otp=False,
        otp_secret="base32secret3232",
        intro_shown=True,
        fido_uuid=None,
    )
    user.include_sender_in_reverse_alias = None
    db.session.commit()

    user.trial_end = None

    LifetimeCoupon.create(code="coupon", nb_used=10)
    db.session.commit()

    # Create a subscription for user
    Subscription.create(
        user_id=user.id,
        cancel_url="https://checkout.paddle.com/subscription/cancel?user=1234",
        update_url="https://checkout.paddle.com/subscription/update?user=1234",
        subscription_id="123",
        event_time=arrow.now(),
        next_bill_date=arrow.now().shift(days=10).date(),
        plan=PlanEnum.monthly,
    )
    db.session.commit()

    api_key = ApiKey.create(user_id=user.id, name="Chrome")
    api_key.code = "code"

    api_key = ApiKey.create(user_id=user.id, name="Firefox")
    api_key.code = "codeFF"

    pgp_public_key = open(get_abs_path("local_data/public-pgp.asc")).read()
    m1 = Mailbox.create(
        user_id=user.id,
        email="*****@*****.**",
        verified=True,
        pgp_public_key=pgp_public_key,
    )
    m1.pgp_finger_print = load_public_key(pgp_public_key)
    db.session.commit()

    for i in range(3):
        if i % 2 == 0:
            a = Alias.create(email=f"e{i}@{FIRST_ALIAS_DOMAIN}",
                             user_id=user.id,
                             mailbox_id=m1.id)
        else:
            a = Alias.create(
                email=f"e{i}@{FIRST_ALIAS_DOMAIN}",
                user_id=user.id,
                mailbox_id=user.default_mailbox_id,
            )
        db.session.commit()

        if i % 5 == 0:
            if i % 2 == 0:
                AliasMailbox.create(alias_id=a.id,
                                    mailbox_id=user.default_mailbox_id)
            else:
                AliasMailbox.create(alias_id=a.id, mailbox_id=m1.id)
        db.session.commit()

        # some aliases don't have any activity
        # if i % 3 != 0:
        #     contact = Contact.create(
        #         user_id=user.id,
        #         alias_id=a.id,
        #         website_email=f"contact{i}@example.com",
        #         reply_email=f"rep{i}@sl.local",
        #     )
        #     db.session.commit()
        #     for _ in range(3):
        #         EmailLog.create(user_id=user.id, contact_id=contact.id)
        #         db.session.commit()

        # have some disabled alias
        if i % 5 == 0:
            a.enabled = False
            db.session.commit()

    CustomDomain.create(user_id=user.id, domain="ab.cd", verified=True)
    CustomDomain.create(user_id=user.id,
                        domain="very-long-domain.com.net.org",
                        verified=True)
    db.session.commit()

    Directory.create(user_id=user.id, name="abcd")
    Directory.create(user_id=user.id, name="xyzt")
    db.session.commit()

    # Create a client
    client1 = Client.create_new(name="Demo", user_id=user.id)
    client1.oauth_client_id = "client-id"
    client1.oauth_client_secret = "client-secret"
    client1.published = True
    db.session.commit()

    RedirectUri.create(client_id=client1.id, uri="https://ab.com")

    client2 = Client.create_new(name="Demo 2", user_id=user.id)
    client2.oauth_client_id = "client-id2"
    client2.oauth_client_secret = "client-secret2"
    client2.published = True
    db.session.commit()

    ClientUser.create(user_id=user.id, client_id=client1.id, name="Fake Name")

    referral = Referral.create(user_id=user.id,
                               code="REFCODE",
                               name="First referral")
    db.session.commit()

    for i in range(6):
        Notification.create(user_id=user.id,
                            message=f"""Hey hey <b>{i}</b> """ * 10)
    db.session.commit()

    User.create(
        email="*****@*****.**",
        name="Winston",
        password="******",
        activated=True,
        referral_id=referral.id,
    )
    db.session.commit()
예제 #17
0
username3 = User('username3', '*****@*****.**',
                 bcrypt.generate_password_hash('12345678'))
username4 = User('username4', '*****@*****.**',
                 bcrypt.generate_password_hash('12345678'))
username5 = User('username5', '*****@*****.**',
                 bcrypt.generate_password_hash('12345678'))
user = User('username', '*****@*****.**',
            bcrypt.generate_password_hash('12345678'))
db.session.add(user)
db.session.add(username1)
db.session.add(username2)
db.session.add(username3)
db.session.add(username4)
db.session.add(username5)

clientA = Client('Client A')
clientB = Client('Client B')
clientC = Client('Client C')
clientD = Client('Client D')
db.session.add(clientA)
db.session.add(clientB)
db.session.add(clientC)
db.session.add(clientD)

policies = ProductArea('Policies')
claims = ProductArea('Claims')
billing = ProductArea('Billing')
reports = ProductArea('Reports')
db.session.add(policies)
db.session.add(claims)
db.session.add(billing)
예제 #18
0
	def __init__(self, id=None):
		if id is not None:
			self.data = Client().find(id)
			self.new = False
		else:	self.new = True
예제 #19
0
 def test_client_model(self):
     c = Client('Client A', '*****@*****.**')
     db.session.add(c)
     db.session.commit()
     assert c.id > 0
     assert 'Client' in repr(c)
예제 #20
0
파일: server.py 프로젝트: cemulus/app
def fake_data():
    LOG.d("create fake data")
    # Remove db if exist
    if os.path.exists("db.sqlite"):
        LOG.d("remove existing db file")
        os.remove("db.sqlite")

    # Create all tables
    db.create_all()

    # Create a user
    user = User.create(
        email="*****@*****.**",
        name="John Wick",
        password="******",
        activated=True,
        is_admin=True,
        # enable_otp=True,
        otp_secret="base32secret3232",
        intro_shown=True,
        fido_uuid=None,
    )
    user.trial_end = None
    db.session.commit()

    # add a profile picture
    file_path = "profile_pic.svg"
    s3.upload_from_bytesio(
        file_path,
        open(os.path.join(ROOT_DIR, "static", "default-icon.svg"), "rb"),
        content_type="image/svg",
    )
    file = File.create(user_id=user.id, path=file_path, commit=True)
    user.profile_picture_id = file.id
    db.session.commit()

    # create a bounced email
    alias = Alias.create_new_random(user)
    db.session.commit()

    bounce_email_file_path = "bounce.eml"
    s3.upload_email_from_bytesio(
        bounce_email_file_path,
        open(os.path.join(ROOT_DIR, "local_data", "email_tests", "2.eml"), "rb"),
        "download.eml",
    )
    refused_email = RefusedEmail.create(
        path=bounce_email_file_path,
        full_report_path=bounce_email_file_path,
        user_id=user.id,
        commit=True,
    )

    contact = Contact.create(
        user_id=user.id,
        alias_id=alias.id,
        website_email="*****@*****.**",
        reply_email="*****@*****.**",
        commit=True,
    )
    EmailLog.create(
        user_id=user.id,
        contact_id=contact.id,
        refused_email_id=refused_email.id,
        bounced=True,
        commit=True,
    )

    LifetimeCoupon.create(code="coupon", nb_used=10, commit=True)

    # Create a subscription for user
    Subscription.create(
        user_id=user.id,
        cancel_url="https://checkout.paddle.com/subscription/cancel?user=1234",
        update_url="https://checkout.paddle.com/subscription/update?user=1234",
        subscription_id="123",
        event_time=arrow.now(),
        next_bill_date=arrow.now().shift(days=10).date(),
        plan=PlanEnum.monthly,
        commit=True,
    )

    CoinbaseSubscription.create(
        user_id=user.id, end_at=arrow.now().shift(days=10), commit=True
    )

    api_key = ApiKey.create(user_id=user.id, name="Chrome")
    api_key.code = "code"

    api_key = ApiKey.create(user_id=user.id, name="Firefox")
    api_key.code = "codeFF"

    pgp_public_key = open(get_abs_path("local_data/public-pgp.asc")).read()
    m1 = Mailbox.create(
        user_id=user.id,
        email="*****@*****.**",
        verified=True,
        pgp_public_key=pgp_public_key,
    )
    m1.pgp_finger_print = load_public_key(pgp_public_key)
    db.session.commit()

    for i in range(3):
        if i % 2 == 0:
            a = Alias.create(
                email=f"e{i}@{FIRST_ALIAS_DOMAIN}", user_id=user.id, mailbox_id=m1.id
            )
        else:
            a = Alias.create(
                email=f"e{i}@{FIRST_ALIAS_DOMAIN}",
                user_id=user.id,
                mailbox_id=user.default_mailbox_id,
            )
        db.session.commit()

        if i % 5 == 0:
            if i % 2 == 0:
                AliasMailbox.create(alias_id=a.id, mailbox_id=user.default_mailbox_id)
            else:
                AliasMailbox.create(alias_id=a.id, mailbox_id=m1.id)
        db.session.commit()

        # some aliases don't have any activity
        # if i % 3 != 0:
        #     contact = Contact.create(
        #         user_id=user.id,
        #         alias_id=a.id,
        #         website_email=f"contact{i}@example.com",
        #         reply_email=f"rep{i}@sl.local",
        #     )
        #     db.session.commit()
        #     for _ in range(3):
        #         EmailLog.create(user_id=user.id, contact_id=contact.id)
        #         db.session.commit()

        # have some disabled alias
        if i % 5 == 0:
            a.enabled = False
            db.session.commit()

    custom_domain1 = CustomDomain.create(user_id=user.id, domain="ab.cd", verified=True)
    db.session.commit()

    Alias.create(
        user_id=user.id,
        email="*****@*****.**",
        mailbox_id=user.default_mailbox_id,
        custom_domain_id=custom_domain1.id,
        commit=True,
    )

    Alias.create(
        user_id=user.id,
        email="*****@*****.**",
        mailbox_id=user.default_mailbox_id,
        custom_domain_id=custom_domain1.id,
        commit=True,
    )

    Directory.create(user_id=user.id, name="abcd")
    Directory.create(user_id=user.id, name="xyzt")
    db.session.commit()

    # Create a client
    client1 = Client.create_new(name="Demo", user_id=user.id)
    client1.oauth_client_id = "client-id"
    client1.oauth_client_secret = "client-secret"
    db.session.commit()

    RedirectUri.create(
        client_id=client1.id, uri="https://your-website.com/oauth-callback"
    )

    client2 = Client.create_new(name="Demo 2", user_id=user.id)
    client2.oauth_client_id = "client-id2"
    client2.oauth_client_secret = "client-secret2"
    db.session.commit()

    ClientUser.create(user_id=user.id, client_id=client1.id, name="Fake Name")

    referral = Referral.create(user_id=user.id, code="Website", name="First referral")
    Referral.create(user_id=user.id, code="Podcast", name="First referral")
    Payout.create(
        user_id=user.id, amount=1000, number_upgraded_account=100, payment_method="BTC"
    )
    Payout.create(
        user_id=user.id,
        amount=5000,
        number_upgraded_account=200,
        payment_method="PayPal",
    )
    db.session.commit()

    for i in range(6):
        Notification.create(user_id=user.id, message=f"""Hey hey <b>{i}</b> """ * 10)
    db.session.commit()

    user2 = User.create(
        email="*****@*****.**",
        password="******",
        activated=True,
        referral_id=referral.id,
    )
    Mailbox.create(user_id=user2.id, email="*****@*****.**", verified=True)
    db.session.commit()

    ManualSubscription.create(
        user_id=user2.id,
        end_at=arrow.now().shift(years=1, days=1),
        comment="Local manual",
        commit=True,
    )
예제 #21
0
    def addUpdateClient(self, old_client_name, new_client_name, product_name,
                        cluster_name, release_number):

        try:
            #check if the new client already exists or not
            exists_client = db.session.query(Client.client_name).filter(
                Client.client_name == new_client_name).scalar() is not None

            #if not exists then add new client record
            if not exists_client:
                client = Client(client_name=new_client_name, is_active=True)
                db.session.add(client)
                db.session.commit()
                print("New client is being added!!!!!!!!")

                # make the old client record as inactive
                if old_client_name != "":
                    self.deactivateClient(old_client_name)
                    self.deactivateCPRC(old_client_name, product_name,
                                        cluster_name, release_number)

                #add new cprc record with new client
                self.addCPRC(new_client_name, product_name, cluster_name,
                             release_number)

            #if the new client already exists then mark it as active client, deactivate cprc for old and add new cprc record
            if exists_client:
                client = db.session.query(Client).filter(
                    Client.client_name == new_client_name).first()
                if client:
                    client.is_active = True
                    db.session.commit()
                exists_cprc = self.checkCPRCExists(new_client_name,
                                                   cluster_name, product_name,
                                                   release_number)

                #if the cprc entry already exists then make it as active
                if exists_cprc is not None:
                    if exists_cprc.is_active == False:
                        exists_cprc.is_active = True
                        db.session.commit()
                        self.deactivateClient(old_client_name)

                        self.deactivateCPRC(old_client_name, product_name,
                                            cluster_name, release_number)
                    return "Client-cprc record already exists"
                #else add new cprc record and deactivate the old record
                else:
                    self.deactivateCPRC(old_client_name, product_name,
                                        cluster_name, release_number)
                    self.addCPRC(new_client_name, product_name, cluster_name,
                                 release_number)
        except Exception as ex:
            date = datetime.utcnow()
            tb = sys.exc_info()[2]
            errorMsg = str(
                date
            ) + " - File: addUpdateDB.py - Function: addUpdateClient - " + str(
                ex.args) + " - on line " + str(tb.tb_lineno) + " \r\n"
            f.write(errorMsg)
            f.close()
예제 #22
0
 def setUp(self):
     TestFactory.setUp(self)
     client = Client(nombre="AGENCIA TUDAD", email="*****@*****.**")
     db.session.add(client)
     db.session.commit()
     self.path = '/clients'
예제 #23
0
def test_authorize_code_flow_with_openid_scope(flask_client):
    """make sure the authorize redirects user to correct page for the *Code Flow*
    and when the *openid* scope is present
    , ie when response_type=code, openid in scope

    The authorize endpoint should stay the same: return the *code*.
    The token endpoint however should now return id_token in addition to the access_token
    """

    user = login(flask_client)
    client = Client.create_new("test client", user.id)

    db.session.commit()

    # user allows client on the authorization page
    r = flask_client.post(
        url_for(
            "oauth.authorize",
            client_id=client.oauth_client_id,
            state="teststate",
            redirect_uri="http://localhost",
            response_type="code",
            scope="openid",  # openid is in scope
        ),
        data={
            "button": "allow",
            "suggested-email": "[email protected]",
            "suggested-name": "AB CD"
        },
        # user will be redirected to client page, do not allow redirection here
        # to assert the redirect url
        # follow_redirects=True,
    )

    assert r.status_code == 302  # user gets redirected back to client page

    # r.location will have this form http://localhost?state=teststate&code=knuyjepwvg
    o = urlparse(r.location)
    assert o.netloc == "localhost"
    assert not o.fragment

    # parse the query, should return something like
    # {'state': ['teststate'], 'code': ['knuyjepwvg'], 'scope': ["openid"]}
    queries = parse_qs(o.query)
    assert len(queries) == 3

    assert queries["state"] == ["teststate"]
    assert len(queries["code"]) == 1

    # Exchange the code to get access_token
    basic_auth_headers = base64.b64encode(
        f"{client.oauth_client_id}:{client.oauth_client_secret}".encode(
        )).decode("utf-8")

    r = flask_client.post(
        url_for("oauth.token"),
        headers={"Authorization": "Basic " + basic_auth_headers},
        data={
            "grant_type": "authorization_code",
            "code": queries["code"][0]
        },
    )

    # r.json should have this format
    # {
    #   'access_token': 'avmhluhonsouhcwwailydwvhankspptgidoggcbu',
    #   'expires_in': 3600,
    #   'scope': '',
    #   'token_type': 'bearer',
    #   'user': {
    #     'avatar_url': None,
    #     'client': 'test client',
    #     'email': '[email protected]',
    #     'email_verified': True,
    #     'id': 1,
    #     'name': 'AB CD'
    #   }
    # }
    assert r.status_code == 200
    assert r.json["access_token"]
    assert r.json["expires_in"] == 3600
    assert r.json["scope"] == "openid"
    assert r.json["token_type"] == "Bearer"

    assert r.json["user"] == {
        "avatar_url": None,
        "client": "test client",
        "email": "[email protected]",
        "email_verified": True,
        "id": 1,
        "name": "AB CD",
        "sub": "1",
    }

    # id_token must be returned
    assert r.json["id_token"]

    # id_token must be a valid, correctly signed JWT
    assert verify_id_token(r.json["id_token"])
예제 #24
0
from app import db
from datetime import datetime
from app.models import Product, Product_Release, Client

#this file cretes the database schema and pre populates the table
db.create_all()
product = Product(product_name="UNKNOWN")
client = Client(client_name="UNKNOWN")
product_release = Product_Release(product_id=1, release_number="UNKNOWN",inserted_at=datetime.utcnow())
db.session.add(product)
db.session.add(client)
db.session.add(product_release)
db.session.commit()
print("DB Created")
예제 #25
0
def initial(request):
    if Company.objects.count() == 0:
        Company.objects.create(name="pushe")

    Criteria.objects.all().delete()
    my_tickets = Criteria.objects.create(name="My Tickets")
    i_follow = Criteria.objects.create(name="Tickets I Follow")
    my_team = Criteria.objects.create(name="My Team's Tickets")
    unassigned = Criteria.objects.create(name="Unassigned Tickets")
    all = Criteria.objects.create(name="All Tickets")

    clause_my_tickets = CriteriaClause.objects.create(criteria=my_tickets)
    clause_i_follow = CriteriaClause.objects.create(criteria=i_follow)
    clause_my_team = CriteriaClause.objects.create(criteria=my_team)
    clause_unassigned = CriteriaClause.objects.create(criteria=unassigned)
    clause_all = CriteriaClause.objects.create(criteria=all)

    single_my_tickets = SingleCriteria.objects.create(
        criteria_clause=clause_my_tickets,
        field="assigned_to",
        operation="is",
        value="shooka_current_agent")
    single_i_follow = SingleCriteria.objects.create(
        criteria_clause=clause_i_follow,
        field="followers",
        operation="is",
        value="shooka_current_agent")
    single_my_team = SingleCriteria.objects.create(
        criteria_clause=clause_my_team,
        field="assigned_team",
        operation="is",
        value="shooka_current_agent_team")
    single_unassigned = SingleCriteria.objects.create(
        criteria_clause=clause_unassigned,
        field="assigned_to",
        operation="isnull",
        value="True",
        value_type="boolean")
    single_all = SingleCriteria.objects.create(criteria_clause=clause_all,
                                               field="pk",
                                               operation="isnull",
                                               value="",
                                               value_type="boolean")

    if User.objects.count() == 0:
        user = User.objects.create(first_name="amirhossein",
                                   email="*****@*****.**",
                                   username="******",
                                   company=Company.objects.first(),
                                   is_staff=True,
                                   is_superuser=True)
        user.set_password("123123")
        user.save()

    Client.objects.all().delete()
    Message.objects.all().delete()
    Ticket.objects.all().delete()

    for i in range(100):
        client_profile = ClientProfile(name=generate_text(5) + "client")
        client_profile.save()
        client = Client(profile=client_profile,
                        email=generate_text(5) + "@gmail.com")
        client.save()
        message = Message(client_sender=client,
                          title=generate_text(15),
                          content='<p>' + generate_text(20) + '</p>')
        message.save()
    return HttpResponse("done")
예제 #26
0
def toggl_api(duration=None):

    # Check WorkSpace
    workspace = Workspace.query.filter_by(id=WORKSPACE_ID).first()
    if workspace is None:
        workspace = Workspace(id=WORKSPACE_ID, name='Vitamin')
        db.session.add(workspace)
        db.session.commit()

    PARAMET_URL = urllib.parse.urlencode({
        'workspace_id': workspace.id,
        'since': '2018-09-01T00:00:00Z',  # Sep 2018
        'until': '2018-10-31T00:00:00Z',  # Out 2010
        'user_agent': USER_AGENT,
    })

    # GET all Workspace members
    users = toggl.request(''.join([WORKSPACES_URL, str(workspace.id), '/users']))
    for user in users:
        member = Member.query.filter_by(id=user.get('id')).first()
        if member is None:
            member = Member(
                id=user.get('id'), name=user.get('fullname'), email=user.get('email'))
            db.session.add(member)
        db.session.commit()

    # GET Detailed report time entries
    response = toggl.request(''.join([REPORTS_URL, 'details?', PARAMET_URL]))
    for data in response.get('data'):

        client = Client.query.filter_by(name=data.get('client')).first()
        if client is None:
            client = Client(name=data.get('client') or '(no client)')
            db.session.add(client)

        member = Member.query.filter_by(id=data.get('uid')).first()
        if member is None:
            member = Member(id=data.get('uid'), name=data.get('user'))
            db.session.add(member)

        project = Project.query.filter_by(id=data.get('pid')).first()
        if project is None:

            project = Project(
                name=data.get('project') or '(without a project)',
                workspace_id=workspace.id,
                client_id=client.id)

            if data.get('pid') is not None:
                project.id = data.get('pid')

                # GET all Project members
                project_users = toggl.request(''.join(
                    [PROJECTS_URL, str(data.get('pid')), '/project_users']))
                for user in project_users:
                    member = Member.query.filter_by(id=user.get('uid')).first()
                    project.members.append(member)

            db.session.add(project)
            db.session.commit()

        if data.get('dur') > DEFAULT_LONG_TASK:
            task = Task.query.filter_by(id=data.get('id')).first()
            if task is None:
                task = Task(
                    id=data.get('id'),
                    name=data.get('description') or '(no description)',
                    project_id=project.id,
                    start=datetime.datetime.fromisoformat(data.get('start')),
                    end=datetime.datetime.fromisoformat(data.get('end')),
                    duration=data.get('dur'))
                db.session.add(task)

    db.session.commit()
예제 #27
0
def authorize():
    """
    Redirected from client when user clicks on "Login with Server".
    This is a GET request with the following field in url
    - client_id
    - (optional) state
    - response_type: must be code
    """
    oauth_client_id = request.args.get("client_id")
    state = request.args.get("state")
    scope = request.args.get("scope")
    redirect_uri = request.args.get("redirect_uri")
    response_mode = request.args.get("response_mode")
    nonce = request.args.get("nonce")

    try:
        response_types: [ResponseType] = get_response_types(request)
    except ValueError:
        return (
            "response_type must be code, token, id_token or certain combination of these."
            " Please see /.well-known/openid-configuration to see what response_type are supported ",
            400,
        )

    if set(response_types) not in SUPPORTED_OPENID_FLOWS:
        return (
            f"SimpleLogin only support the following OIDC flows: {SUPPORTED_OPENID_FLOWS_STR}",
            400,
        )

    if not redirect_uri:
        LOG.d("no redirect uri")
        return "redirect_uri must be set", 400

    client = Client.get_by(oauth_client_id=oauth_client_id)
    if not client:
        final_redirect_uri = (
            f"{redirect_uri}?error=invalid_client_id&client_id={oauth_client_id}"
        )
        return redirect(final_redirect_uri)

    # check if redirect_uri is valid
    # allow localhost by default
    hostname, scheme = get_host_name_and_scheme(redirect_uri)
    if hostname != "localhost" and hostname != "127.0.0.1":
        # support custom scheme for mobile app
        if scheme == "http":
            final_redirect_uri = f"{redirect_uri}?error=http_not_allowed"
            return redirect(final_redirect_uri)

        if not RedirectUri.get_by(client_id=client.id, uri=redirect_uri):
            final_redirect_uri = f"{redirect_uri}?error=unknown_redirect_uri"
            return redirect(final_redirect_uri)

    # redirect from client website
    if request.method == "GET":
        if current_user.is_authenticated:
            suggested_email, other_emails, email_suffix = None, [], None
            suggested_name, other_names = None, []

            # user has already allowed this client
            client_user: ClientUser = ClientUser.get_by(
                client_id=client.id, user_id=current_user.id
            )
            user_info = {}
            if client_user:
                LOG.debug("user %s has already allowed client %s", current_user, client)
                user_info = client_user.get_user_info()
            else:
                suggested_email, other_emails = current_user.suggested_emails(
                    client.name
                )
                suggested_name, other_names = current_user.suggested_names()
                email_suffix = random_word()

            return render_template(
                "oauth/authorize.html",
                client=client,
                user_info=user_info,
                client_user=client_user,
                Scope=Scope,
                suggested_email=suggested_email,
                personal_email=current_user.email,
                suggested_name=suggested_name,
                other_names=other_names,
                other_emails=other_emails,
                email_suffix=email_suffix,
                EMAIL_DOMAIN=EMAIL_DOMAIN,
            )
        else:
            # after user logs in, redirect user back to this page
            return render_template(
                "oauth/authorize_nonlogin_user.html",
                client=client,
                next=request.url,
                Scope=Scope,
            )
    else:  # user allows or denies
        if request.form.get("button") == "deny":
            LOG.debug("User %s denies Client %s", current_user, client)
            final_redirect_uri = f"{redirect_uri}?error=deny&state={state}"
            return redirect(final_redirect_uri)

        LOG.debug("User %s allows Client %s", current_user, client)
        client_user = ClientUser.get_by(client_id=client.id, user_id=current_user.id)

        # user has already allowed this client, user cannot change information
        if client_user:
            LOG.d("user %s has already allowed client %s", current_user, client)
        else:
            email_suffix = request.form.get("email-suffix")
            custom_email_prefix = request.form.get("custom-email-prefix")
            chosen_email = request.form.get("suggested-email")

            suggested_name = request.form.get("suggested-name")
            custom_name = request.form.get("custom-name")

            use_default_avatar = request.form.get("avatar-choice") == "default"

            gen_email = None
            if custom_email_prefix:
                # check if user can generate custom email
                if not current_user.can_create_new_alias():
                    raise Exception(f"User {current_user} cannot create custom email")

                email = f"{convert_to_id(custom_email_prefix)}.{email_suffix}@{EMAIL_DOMAIN}"
                LOG.d("create custom email alias %s for user %s", email, current_user)

                if GenEmail.get_by(email=email) or DeletedAlias.get_by(email=email):
                    LOG.error("email %s already used, very rare!", email)
                    flash(f"alias {email} already used", "error")
                    return redirect(request.url)

                gen_email = GenEmail.create(email=email, user_id=current_user.id)
                db.session.flush()
            else:  # user picks an email from suggestion
                if chosen_email != current_user.email:
                    gen_email = GenEmail.get_by(email=chosen_email)
                    if not gen_email:
                        gen_email = GenEmail.create(
                            email=chosen_email, user_id=current_user.id
                        )
                        db.session.flush()

            client_user = ClientUser.create(
                client_id=client.id, user_id=current_user.id
            )
            if gen_email:
                client_user.gen_email_id = gen_email.id

            if custom_name:
                LOG.d(
                    "use custom name %s for user %s client %s",
                    custom_name,
                    current_user,
                    client,
                )
                client_user.name = custom_name
            elif suggested_name != current_user.name:
                LOG.d(
                    "use another name %s for user %s client %s",
                    custom_name,
                    current_user,
                    client,
                )
                client_user.name = suggested_name

            if use_default_avatar:
                # use default avatar
                LOG.d("use default avatar for user %s client %s", current_user, client)
                client_user.default_avatar = True

            db.session.flush()
            LOG.d("create client-user for client %s, user %s", client, current_user)

        redirect_args = {}

        if state:
            redirect_args["state"] = state
        else:
            LOG.warning(
                "more security reason, state should be added. client %s", client
            )

        if scope:
            redirect_args["scope"] = scope

        auth_code = None
        if ResponseType.CODE in response_types:
            # Create authorization code
            auth_code = AuthorizationCode.create(
                client_id=client.id,
                user_id=current_user.id,
                code=random_string(),
                scope=scope,
                redirect_uri=redirect_uri,
                response_type=response_types_to_str(response_types),
            )
            db.session.add(auth_code)
            redirect_args["code"] = auth_code.code

        oauth_token = None
        if ResponseType.TOKEN in response_types:
            # create access-token
            oauth_token = OauthToken.create(
                client_id=client.id,
                user_id=current_user.id,
                scope=scope,
                redirect_uri=redirect_uri,
                access_token=generate_access_token(),
                response_type=response_types_to_str(response_types),
            )
            db.session.add(oauth_token)
            redirect_args["access_token"] = oauth_token.access_token

        if ResponseType.ID_TOKEN in response_types:
            redirect_args["id_token"] = make_id_token(
                client_user,
                nonce,
                oauth_token.access_token if oauth_token else None,
                auth_code.code if auth_code else None,
            )

        db.session.commit()

        # should all params appended the url using fragment (#) or query
        fragment = False

        if response_mode and response_mode == "fragment":
            fragment = True

        # if response_types contain "token" => implicit flow => should use fragment
        # except if client sets explicitly response_mode
        if not response_mode:
            if ResponseType.TOKEN in response_types:
                fragment = True

        # construct redirect_uri with redirect_args
        return redirect(construct_url(redirect_uri, redirect_args, fragment))
예제 #28
0
파일: setting.py 프로젝트: arnobferdous/app
def setting():
    form = SettingForm()
    promo_form = PromoCodeForm()
    change_email_form = ChangeEmailForm()

    email_change = EmailChange.get_by(user_id=current_user.id)
    if email_change:
        pending_email = email_change.new_email
    else:
        pending_email = None

    if request.method == "POST":
        if request.form.get("form-name") == "update-email":
            if change_email_form.validate():
                if (change_email_form.email.data.lower().strip() !=
                        current_user.email and not pending_email):
                    new_email = change_email_form.email.data.strip().lower()

                    # check if this email is not already used
                    if personal_email_already_used(new_email) or Alias.get_by(
                            email=new_email):
                        flash(f"Email {new_email} already used", "error")
                    elif not email_domain_can_be_used_as_mailbox(new_email):
                        flash(
                            "You cannot use this email address as your personal inbox.",
                            "error",
                        )
                    else:
                        email_change = EmailChange.create(
                            user_id=current_user.id,
                            code=random_string(
                                60),  # todo: make sure the code is unique
                            new_email=new_email,
                        )
                        db.session.commit()
                        send_change_email_confirmation(current_user,
                                                       email_change)
                        flash(
                            "A confirmation email is on the way, please check your inbox",
                            "success",
                        )
                        return redirect(url_for("dashboard.setting"))
        if request.form.get("form-name") == "update-profile":
            if form.validate():
                profile_updated = False
                # update user info
                if form.name.data != current_user.name:
                    current_user.name = form.name.data
                    db.session.commit()
                    profile_updated = True

                if form.profile_picture.data:
                    file_path = random_string(30)
                    file = File.create(user_id=current_user.id, path=file_path)

                    s3.upload_from_bytesio(
                        file_path, BytesIO(form.profile_picture.data.read()))

                    db.session.flush()
                    LOG.d("upload file %s to s3", file)

                    current_user.profile_picture_id = file.id
                    db.session.commit()
                    profile_updated = True

                if profile_updated:
                    flash(f"Your profile has been updated", "success")
                    return redirect(url_for("dashboard.setting"))

        elif request.form.get("form-name") == "change-password":
            flash(
                "You are going to receive an email containing instructions to change your password",
                "success",
            )
            send_reset_password_email(current_user)
            return redirect(url_for("dashboard.setting"))

        elif request.form.get("form-name") == "notification-preference":
            choose = request.form.get("notification")
            if choose == "on":
                current_user.notification = True
            else:
                current_user.notification = False
            db.session.commit()
            flash("Your notification preference has been updated", "success")
            return redirect(url_for("dashboard.setting"))

        elif request.form.get("form-name") == "delete-account":
            LOG.warning("Delete account %s", current_user)
            User.delete(current_user.id)
            db.session.commit()
            flash("Your account has been deleted", "success")
            logout_user()
            return redirect(url_for("auth.register"))

        elif request.form.get("form-name") == "change-alias-generator":
            scheme = int(request.form.get("alias-generator-scheme"))
            if AliasGeneratorEnum.has_value(scheme):
                current_user.alias_generator = scheme
                db.session.commit()
            flash("Your preference has been updated", "success")
            return redirect(url_for("dashboard.setting"))

        elif request.form.get(
                "form-name") == "change-random-alias-default-domain":
            default_domain = request.form.get("random-alias-default-domain")
            if default_domain:
                default_domain_id = int(default_domain)
                # sanity check
                domain = CustomDomain.get(default_domain_id)
                if (not domain or domain.user_id != current_user.id
                        or not domain.verified):
                    flash(
                        "Something went wrong, sorry for the inconvenience. Please retry. ",
                        "error",
                    )
                    return redirect(url_for("dashboard.setting"))
                current_user.default_random_alias_domain_id = default_domain_id
            else:
                current_user.default_random_alias_domain_id = None

            db.session.commit()
            flash("Your preference has been updated", "success")
            return redirect(url_for("dashboard.setting"))

        elif request.form.get("form-name") == "change-sender-format":
            sender_format = int(request.form.get("sender-format"))
            if SenderFormatEnum.has_value(sender_format):
                current_user.sender_format = sender_format
                db.session.commit()
                flash("Your sender format preference has been updated",
                      "success")
            db.session.commit()
            return redirect(url_for("dashboard.setting"))

        elif request.form.get("form-name") == "replace-ra":
            choose = request.form.get("replace-ra")
            if choose == "on":
                current_user.replace_reverse_alias = True
            else:
                current_user.replace_reverse_alias = False
            db.session.commit()
            flash("Your preference has been updated", "success")
            return redirect(url_for("dashboard.setting"))

        elif request.form.get("form-name") == "export-data":
            data = {
                "email": current_user.email,
                "name": current_user.name,
                "aliases": [],
                "apps": [],
                "custom_domains": [],
            }

            for alias in Alias.filter_by(
                    user_id=current_user.id).all():  # type: Alias
                data["aliases"].append(
                    dict(email=alias.email, enabled=alias.enabled))

            for custom_domain in CustomDomain.filter_by(
                    user_id=current_user.id).all():
                data["custom_domains"].append(custom_domain.domain)

            for app in Client.filter_by(
                    user_id=current_user.id):  # type: Client
                data["apps"].append(
                    dict(name=app.name,
                         home_url=app.home_url,
                         published=app.published))

            return Response(
                json.dumps(data),
                mimetype="text/json",
                headers={
                    "Content-Disposition": "attachment;filename=data.json"
                },
            )

    manual_sub = ManualSubscription.get_by(user_id=current_user.id)
    return render_template(
        "dashboard/setting.html",
        form=form,
        PlanEnum=PlanEnum,
        SenderFormatEnum=SenderFormatEnum,
        promo_form=promo_form,
        change_email_form=change_email_form,
        pending_email=pending_email,
        AliasGeneratorEnum=AliasGeneratorEnum,
        manual_sub=manual_sub,
        FIRST_ALIAS_DOMAIN=FIRST_ALIAS_DOMAIN,
    )
예제 #29
0
from app import create_app,db
from app.models import FeatureRequest, Client,ProductArea
from datetime import datetime


app = create_app()
app.app_context().push()
with app.app_context():
    db.create_all()
    db.session.add(Client(name='Client A'))
    db.session.add(Client(name='Client B'))
    db.session.add(Client(name='Client C'))
    db.session.add(ProductArea(name='Policies'))
    db.session.add(ProductArea(name='Billings'))
    db.session.add(ProductArea(name='Claims'))
    db.session.add(ProductArea(name='Reports'))
    featureRequest = FeatureRequest(
        title='First Title',
        description='First Description',
        target_date=datetime.strptime('2019/05/24', '%Y/%m/%d'),
        client_priority=1,
        client_id=3,
        product_area_id=2
    )
    db.session.add(featureRequest)
    featureRequest = FeatureRequest(
        title='Second Title',
        description='Second Description',
        target_date=datetime.strptime('2019/05/31', '%Y/%m/%d'),
        client_priority=1,
        client_id=2,
예제 #30
0
def test_authorize_token_id_token_flow(flask_client):
    """make sure the authorize redirects user to correct page for the *ID-Token Token Flow*
    , ie when response_type=id_token,token
    The /authorize endpoint should return an id_token and access_token
    id_token, once decoded, should contain *at_hash* in payload
    """

    user = login(flask_client)
    client = Client.create_new("test client", user.id)

    db.session.commit()

    # user allows client on the authorization page
    r = flask_client.post(
        url_for(
            "oauth.authorize",
            client_id=client.oauth_client_id,
            state="teststate",
            redirect_uri="http://localhost",
            response_type="id_token token",  # id_token,token flow
        ),
        data={
            "button": "allow",
            "suggested-email": "[email protected]",
            "suggested-name": "AB CD"
        },
        # user will be redirected to client page, do not allow redirection here
        # to assert the redirect url
        # follow_redirects=True,
    )

    assert r.status_code == 302  # user gets redirected back to client page

    # r.location will have this form http://localhost?state=teststate&code=knuyjepwvg
    o = urlparse(r.location)
    assert o.netloc == "localhost"
    assert o.fragment
    assert not o.query

    # parse the fragment, should return something like
    # {'state': ['teststate'], 'id_token': ['knuyjepwvg']}
    queries = parse_qs(o.fragment)
    assert len(queries) == 3

    assert queries["state"] == ["teststate"]

    # access_token must be returned
    assert len(queries["id_token"]) == 1
    assert len(queries["access_token"]) == 1

    # id_token must be a valid, correctly signed JWT
    id_token = queries["id_token"][0]
    assert verify_id_token(id_token)

    # make sure jwt has all the necessary fields
    jwt = decode_id_token(id_token)

    # payload should have this format
    # {
    #   'at_hash': 'jLDmoGpuOIHwxeyFEe9SKw',
    #   'aud': 'testclient-sywcpwsyua',
    #   'auth_time': 1565450736,
    #   'avatar_url': None,
    #   'client': 'test client',
    #   'email': '[email protected]',
    #   'email_verified': True,
    #   'exp': 1565454336,
    #   'iat': 1565450736,
    #   'id': 1,
    #   'iss': 'http://localhost',
    #   'name': 'AB CD',
    #   'sub': '1'
    # }
    payload = json.loads(jwt.claims)

    # at_hash MUST be present when the flow is id_token,token
    assert "at_hash" in payload

    assert "aud" in payload
    assert "auth_time" in payload
    assert "avatar_url" in payload
    assert "client" in payload
    assert "email" in payload
    assert "email_verified" in payload
    assert "exp" in payload
    assert "iat" in payload
    assert "id" in payload
    assert "iss" in payload
    assert "name" in payload
    assert "sub" in payload
예제 #31
0
def feature_requests():
    if request.method == 'POST':
        title = str(request.form['title'])
        description = str(request.form['description'])
        if "client" in request.form and request.form['client'] != "":
            client = Client(name=request.form['client'])
            db.session.add(client)
            db.session.commit()
            client_id = client.id
        else:
            client_id = request.form['client_id']

        if "product_area" in request.form and request.form[
                'product_area'] != "":
            product_area = ProductArea(name=request.form['product_area'])
            db.session.add(product_area)
            db.session.commit()
            product_area_id = product_area.id
        else:
            product_area_id = request.form['product_area_id']

        target_date = str(request.form['target_date'])
        priority = int(request.form['priority'])

        feature_request = FeatureRequest(title=title,
                                         description=description,
                                         client_id=client_id,
                                         target_date=target_date,
                                         priority=priority,
                                         product_area_id=product_area_id)

        db.session.add(feature_request)

        priority_to_update = priority
        feat_requests_to_update_count = FeatureRequest.query.filter_by(
            client_id=client_id, priority=priority_to_update).count()
        while feat_requests_to_update_count > 1:
            feat_requests_to_update = FeatureRequest.query.filter_by(
                client_id=client_id,
                priority=priority_to_update).order_by('id').first()
            feat_requests_to_update.priority = feat_requests_to_update.priority + 1
            priority_to_update = priority_to_update + 1
            feat_requests_to_update_count = FeatureRequest.query.filter_by(
                client_id=client_id, priority=priority_to_update).count()

        db.session.commit()
        response = jsonify({
            'id': feature_request.id,
            'title': feature_request.title,
            'description': feature_request.description,
            'client_id': feature_request.client_id,
            'client': feature_request.client.name,
            'target_date': feature_request.target_date,
            'product_area_id': feature_request.product_area_id,
            'product_area': feature_request.product_area.name,
            'priority': feature_request.priority
        })
        response.status_code = 201
        return response
    else:
        feature_requests = FeatureRequest.query.all()
        results = []
        for item in feature_requests:
            results.append({
                'id': item.id,
                'title': item.title,
                'description': item.description,
                'client_id': item.client_id,
                'target_date': item.target_date,
                'client': item.client.name,
                'product_area_id': item.product_area_id,
                'product_area': item.product_area.name,
                'priority': item.priority
            })
        response = jsonify(results)
        response.status_code = 200
        return response
예제 #32
0
def index():
    clients = Client.filter_by(published=True).all()
    return render_template("discover/index.html", clients=clients)
예제 #33
0
	def test_client_good_init(self):
		c = Client('Alice', '*****@*****.**', '+79099946885')
		c.password = '******'
		db.session.add(c)
		self.assertIsNone(db.session.commit())
예제 #34
0
def setting():
    form = SettingForm()
    promo_form = PromoCodeForm()

    email_change = EmailChange.get_by(user_id=current_user.id)
    if email_change:
        pending_email = email_change.new_email
    else:
        pending_email = None

    if request.method == "POST":
        if request.form.get("form-name") == "update-profile":
            if form.validate():
                profile_updated = False
                # update user info
                if form.name.data != current_user.name:
                    current_user.name = form.name.data
                    db.session.commit()
                    profile_updated = True

                if form.profile_picture.data:
                    file_path = random_string(30)
                    file = File.create(path=file_path)

                    s3.upload_from_bytesio(
                        file_path, BytesIO(form.profile_picture.data.read()))

                    db.session.flush()
                    LOG.d("upload file %s to s3", file)

                    current_user.profile_picture_id = file.id
                    db.session.commit()
                    profile_updated = True

                if profile_updated:
                    flash(f"Your profile has been updated", "success")

                if (form.email.data and form.email.data != current_user.email
                        and not pending_email):
                    new_email = form.email.data

                    # check if this email is not used by other user, or as alias
                    if (User.get_by(email=new_email)
                            or GenEmail.get_by(email=new_email)
                            or DeletedAlias.get_by(email=new_email)):
                        flash(f"Email {new_email} already used", "error")
                    elif not can_be_used_as_personal_email(new_email):
                        flash(
                            "You cannot use this email address as your personal inbox.",
                            "error",
                        )
                    else:
                        email_change = EmailChange.create(
                            user_id=current_user.id,
                            code=random_string(
                                60),  # todo: make sure the code is unique
                            new_email=new_email,
                        )
                        db.session.commit()
                        send_change_email_confirmation(current_user,
                                                       email_change)
                        flash(
                            "A confirmation email is on the way, please check your inbox",
                            "success",
                        )

        elif request.form.get("form-name") == "change-password":
            send_reset_password_email(current_user)

        elif request.form.get("form-name") == "notification-preference":
            choose = request.form.get("notification")
            if choose == "on":
                current_user.notification = True
            else:
                current_user.notification = False
            db.session.commit()
            flash("Your notification preference has been updated", "success")

        elif request.form.get("form-name") == "delete-account":
            User.delete(current_user.id)
            db.session.commit()
            flash("Your account has been deleted", "success")
            logout_user()
            return redirect(url_for("auth.register"))

        elif request.form.get("form-name") == "change-alias-generator":
            scheme = int(request.form.get("alias-generator-scheme"))
            if AliasGeneratorEnum.has_value(scheme):
                current_user.alias_generator = scheme
                db.session.commit()
            flash("Your preference has been updated", "success")

        elif request.form.get("form-name") == "export-data":
            data = {
                "email": current_user.email,
                "name": current_user.name,
                "aliases": [],
                "apps": [],
                "custom_domains": [],
            }

            for alias in GenEmail.filter_by(
                    user_id=current_user.id).all():  # type: GenEmail
                data["aliases"].append(
                    dict(email=alias.email, enabled=alias.enabled))

            for custom_domain in CustomDomain.filter_by(
                    user_id=current_user.id).all():
                data["custom_domains"].append(custom_domain.domain)

            for app in Client.filter_by(
                    user_id=current_user.id):  # type: Client
                data["apps"].append(
                    dict(name=app.name,
                         home_url=app.home_url,
                         published=app.published))

            return Response(
                json.dumps(data),
                mimetype="text/json",
                headers={
                    "Content-Disposition": "attachment;filename=data.json"
                },
            )

        return redirect(url_for("dashboard.setting"))

    return render_template(
        "dashboard/setting.html",
        form=form,
        PlanEnum=PlanEnum,
        promo_form=promo_form,
        pending_email=pending_email,
        AliasGeneratorEnum=AliasGeneratorEnum,
    )
예제 #35
0
 def test_func_save(self):
     client = Client(email='email')
     client.save()
     committed_client = Client.query.get(client.id)
     self.assertEqual(committed_client, client)
예제 #36
0
def profile(request):
    """User profile page"""
    context = get_global_context(request)

    if request.method == 'POST':
        user = request.user
        if user.has_perm('app.employee_role'):
            employee = Employee.objects.get(user_id=user.id)
            employee_form = EmployeeProfileForm(request.POST,
                                                request.FILES,
                                                instance=employee)
            user_form = UserProfileForm(request.POST, instance=request.user)

            if user_form.is_valid() and employee_form.is_valid():
                if user_form.has_changed():
                    user.username = user_form.cleaned_data['username']
                    user.email = user_form.cleaned_data['email']
                    user.first_name = user_form.cleaned_data['first_name']
                    user.last_name = user_form.cleaned_data['last_name']
                    user.save()

                if employee_form.has_changed():
                    # saving data
                    if employee_form.cleaned_data['avatar'] and\
                            employee.avatar !=\
                                    employee_form.cleaned_data['avatar']:
                        cur_avatar = employee.avatar
                        employee.avatar = employee_form.cleaned_data['avatar']
                        delete_current_avatar_file(cur_avatar.path)
                    employee.save()
            else:
                user_data = dict((key, user_form.data[key]) for key in list(
                    set(user_form.data) & set(user_form.fields)))
                current_data_user = User(**user_data)

                employee_data = dict(
                    (key, employee_form.data[key]) for key in list(
                        set(employee_form.data) & set(employee_form.fields))
                    if key != 'avatar')
                current_data_employee = Employee(**employee_data)
                current_data_employee.avatar = employee.avatar

                context.update({
                    'title': employee.get_short_instance_name(),
                    'cur_user': current_data_user,
                    'employee': current_data_employee,
                    'employee_form': employee_form,
                    'user_form': user_form,
                })

            return render_profile(request, context)

        elif user.has_perm('app.client_role'):
            client = Client.objects.get(user_id=request.user.id)
            client_form = ClientProfileForm(request.POST,
                                            request.FILES,
                                            instance=client)
            user_form = UserProfileForm(request.POST, instance=request.user)

            if user_form.is_valid() and client_form.is_valid():
                if user_form.has_changed():
                    user.username = user_form.cleaned_data['username']
                    user.email = user_form.cleaned_data['email']
                    user.first_name = user_form.cleaned_data['first_name']
                    user.last_name = user_form.cleaned_data['last_name']
                    user.save()

                if client_form.has_changed():
                    # saving data
                    client = Client.objects.get(user_id=user.id)
                    client.name = client_form.cleaned_data['name']
                    client.full_name = client_form.cleaned_data['full_name']
                    client.code_ipn = client_form.cleaned_data['code_ipn']
                    client.address = client_form.cleaned_data['address']
                    client.phone = client_form.cleaned_data['phone']
                    client.overall_mark_id =\
                        client_form.data['overall_mark']
                    if client_form.cleaned_data['avatar'] and\
                            client.avatar != client_form.cleaned_data['avatar']:
                        cur_avatar = client.avatar
                        client.avatar = client_form.cleaned_data['avatar']
                        delete_current_avatar_file(cur_avatar.path)
                    client.save()
            else:
                user_data = dict((key, user_form.data[key]) for key in list(
                    set(user_form.data) & set(user_form.fields)))
                current_data_user = User(**user_data)

                client_data = dict(
                    (key, client_form.data[key]) for key in list(
                        set(client_form.data) & set(client_form.fields))
                    if key != 'avatar')
                client_data.update({
                    'overall_mark':
                    Mark.objects.get(id=client_form.data['overall_mark']),
                })
                current_data_client = Client(**client_data)
                current_data_client.balance = client.balance
                current_data_client.avatar = client.avatar

                context.update({
                    'title': client.get_title_name(),
                    'cur_user': current_data_user,
                    'client': current_data_client,
                    'client_form': client_form,
                    'user_form': user_form,
                })

            return render_profile(request, context)

    else:
        return render_profile(request, context)
예제 #37
0
def token():
    """
    Calls by client to exchange the access token given the authorization code.
    The client authentications using Basic Authentication.
    The form contains the following data:
    - grant_type: must be "authorization_code"
    - code: the code obtained in previous step
    """
    # Basic authentication
    oauth_client_id = (request.authorization and request.authorization.username
                       ) or request.form.get("client_id")

    oauth_client_secret = (request.authorization
                           and request.authorization.password
                           ) or request.form.get("client_secret")

    client = Client.filter_by(oauth_client_id=oauth_client_id,
                              oauth_client_secret=oauth_client_secret).first()

    if not client:
        return jsonify(error="wrong client-id or client-secret"), 400

    # Get code from form data
    grant_type = request.form.get("grant_type")
    code = request.form.get("code")

    # sanity check
    if grant_type != "authorization_code":
        return jsonify(error="grant_type must be authorization_code"), 400

    auth_code: AuthorizationCode = AuthorizationCode.filter_by(
        code=code).first()
    if not auth_code:
        return jsonify(error=f"no such authorization code {code}"), 400
    elif auth_code.is_expired():
        AuthorizationCode.delete(auth_code.id)
        db.session.commit()
        LOG.d("delete expired authorization code:%s", auth_code)
        return jsonify(error=f"{code} already expired"), 400

    if auth_code.client_id != client.id:
        return jsonify(error="are you sure this code belongs to you?"), 400

    LOG.debug("Create Oauth token for user %s, client %s", auth_code.user,
              auth_code.client)

    # Create token
    oauth_token = OauthToken.create(
        client_id=auth_code.client_id,
        user_id=auth_code.user_id,
        scope=auth_code.scope,
        redirect_uri=auth_code.redirect_uri,
        access_token=generate_access_token(),
        response_type=auth_code.response_type,
    )
    db.session.add(oauth_token)

    # Auth code can be used only once
    AuthorizationCode.delete(auth_code.id)

    db.session.commit()

    client_user: ClientUser = ClientUser.get_by(client_id=auth_code.client_id,
                                                user_id=auth_code.user_id)

    user_data = client_user.get_user_info()

    res = {
        "access_token": oauth_token.access_token,
        "token_type": "Bearer",
        "expires_in": 3600,
        "scope": auth_code.scope,
        "user": user_data,  # todo: remove this
    }

    if oauth_token.scope and Scope.OPENID.value in oauth_token.scope:
        res["id_token"] = make_id_token(client_user)

    # Also return id_token if the initial flow is "code,id_token"
    # cf https://medium.com/@darutk/diagrams-of-all-the-openid-connect-flows-6968e3990660
    response_types = get_response_types_from_str(auth_code.response_type)
    if ResponseType.ID_TOKEN in response_types:
        res["id_token"] = make_id_token(client_user)

    return jsonify(res)
예제 #38
0
파일: signals.py 프로젝트: ojengwa/apipanda
def add_to_org(sender, **kwargs):
    org = sender.objects.last()
    user = org.creator

    member, created = OrganisationMember.objects.get_or_create(
        org=org, member=user)

    if created:
        tld = tldextract.extract(org.url)

        client = Client()
        client.name = org.name
        client.organisation = org
        client.schema_name = org.slug
        client.paid_until = datetime.now() + timedelta(days=90)
        try:
            client.domain_url = tld.domain
            client.save()
        except KeyError:
            try:
                client.domain_url = tld.domain + '-' + tld.subdomain
                client.save()
            except KeyError:
                client.domain_url = org.slug
                client.save()
예제 #39
0
def authorize():
    """
    Redirected from client when user clicks on "Login with Server".
    This is a GET request with the following field in url
    - client_id
    - (optional) state
    - response_type: must be code
    """
    oauth_client_id = request.args.get("client_id")
    state = request.args.get("state")
    scope = request.args.get("scope")
    redirect_uri = request.args.get("redirect_uri")
    response_mode = request.args.get("response_mode")
    nonce = request.args.get("nonce")

    try:
        response_types: [ResponseType] = get_response_types(request)
    except ValueError:
        return (
            "response_type must be code, token, id_token or certain combination of these."
            " Please see /.well-known/openid-configuration to see what response_type are supported ",
            400,
        )

    if set(response_types) not in SUPPORTED_OPENID_FLOWS:
        return (
            f"SimpleLogin only support the following OIDC flows: {SUPPORTED_OPENID_FLOWS_STR}",
            400,
        )

    if not redirect_uri:
        LOG.d("no redirect uri")
        return "redirect_uri must be set", 400

    client = Client.get_by(oauth_client_id=oauth_client_id)
    if not client:
        final_redirect_uri = (
            f"{redirect_uri}?error=invalid_client_id&client_id={oauth_client_id}"
        )
        return redirect(final_redirect_uri)

    # check if redirect_uri is valid
    # allow localhost by default
    hostname, scheme = get_host_name_and_scheme(redirect_uri)
    if hostname != "localhost" and hostname != "127.0.0.1":
        # support custom scheme for mobile app
        if scheme == "http":
            final_redirect_uri = f"{redirect_uri}?error=http_not_allowed"
            return redirect(final_redirect_uri)

        if not RedirectUri.get_by(client_id=client.id, uri=redirect_uri):
            final_redirect_uri = f"{redirect_uri}?error=unknown_redirect_uri"
            return redirect(final_redirect_uri)

    # redirect from client website
    if request.method == "GET":
        if current_user.is_authenticated:
            suggested_email, other_emails, email_suffix = None, [], None
            suggested_name, other_names = None, []

            # user has already allowed this client
            client_user: ClientUser = ClientUser.get_by(
                client_id=client.id, user_id=current_user.id)
            user_info = {}
            if client_user:
                LOG.debug("user %s has already allowed client %s",
                          current_user, client)
                user_info = client_user.get_user_info()
            else:
                suggested_email, other_emails = current_user.suggested_emails(
                    client.name)
                suggested_name, other_names = current_user.suggested_names()

                user_custom_domains = [
                    cd.domain for cd in current_user.verified_custom_domains()
                ]
                # List of (is_custom_domain, alias-suffix)
                suffixes = []

                # put custom domain first
                for alias_domain in user_custom_domains:
                    suffixes.append((True, "@" + alias_domain))

                # then default domain
                for domain in ALIAS_DOMAINS:
                    suffixes.append((
                        False,
                        ("" if DISABLE_ALIAS_SUFFIX else "." + random_word()) +
                        "@" + domain,
                    ))

            return render_template(
                "oauth/authorize.html",
                Scope=Scope,
                EMAIL_DOMAIN=EMAIL_DOMAIN,
                **locals(),
            )
        else:
            # after user logs in, redirect user back to this page
            return render_template(
                "oauth/authorize_nonlogin_user.html",
                client=client,
                next=request.url,
                Scope=Scope,
            )
    else:  # POST - user allows or denies
        if request.form.get("button") == "deny":
            LOG.debug("User %s denies Client %s", current_user, client)
            final_redirect_uri = f"{redirect_uri}?error=deny&state={state}"
            return redirect(final_redirect_uri)

        LOG.debug("User %s allows Client %s", current_user, client)
        client_user = ClientUser.get_by(client_id=client.id,
                                        user_id=current_user.id)

        # user has already allowed this client, user cannot change information
        if client_user:
            LOG.d("user %s has already allowed client %s", current_user,
                  client)
        else:
            alias_prefix = request.form.get("prefix")
            alias_suffix = request.form.get("suffix")

            gen_email = None

            # user creates a new alias, not using suggested alias
            if alias_prefix:
                # should never happen as this is checked on the front-end
                if not current_user.can_create_new_alias():
                    raise Exception(
                        f"User {current_user} cannot create custom email")

                user_custom_domains = [
                    cd.domain for cd in current_user.verified_custom_domains()
                ]

                from app.dashboard.views.custom_alias import verify_prefix_suffix

                if verify_prefix_suffix(current_user, alias_prefix,
                                        alias_suffix, user_custom_domains):
                    full_alias = alias_prefix + alias_suffix

                    if GenEmail.get_by(
                            email=full_alias) or DeletedAlias.get_by(
                                email=full_alias):
                        LOG.error("alias %s already used, very rare!",
                                  full_alias)
                        flash(f"Alias {full_alias} already used", "error")
                        return redirect(request.url)
                    else:
                        gen_email = GenEmail.create(
                            user_id=current_user.id,
                            email=full_alias,
                            mailbox_id=current_user.default_mailbox_id,
                        )

                        # get the custom_domain_id if alias is created with a custom domain
                        alias_domain = get_email_domain_part(full_alias)
                        custom_domain = CustomDomain.get_by(
                            domain=alias_domain)
                        if custom_domain:
                            gen_email.custom_domain_id = custom_domain.id

                        db.session.flush()
                        flash(f"Alias {full_alias} has been created",
                              "success")
                # only happen if the request has been "hacked"
                else:
                    flash("something went wrong", "warning")
                    return redirect(request.url)
            # User chooses one of the suggestions
            else:
                chosen_email = request.form.get("suggested-email")
                # todo: add some checks on chosen_email
                if chosen_email != current_user.email:
                    gen_email = GenEmail.get_by(email=chosen_email)
                    if not gen_email:
                        gen_email = GenEmail.create(
                            email=chosen_email,
                            user_id=current_user.id,
                            mailbox_id=current_user.default_mailbox_id,
                        )
                        db.session.flush()

            suggested_name = request.form.get("suggested-name")
            custom_name = request.form.get("custom-name")

            use_default_avatar = request.form.get("avatar-choice") == "default"

            client_user = ClientUser.create(client_id=client.id,
                                            user_id=current_user.id)
            if gen_email:
                client_user.gen_email_id = gen_email.id

            if custom_name:
                client_user.name = custom_name
            elif suggested_name != current_user.name:
                client_user.name = suggested_name

            if use_default_avatar:
                # use default avatar
                LOG.d("use default avatar for user %s client %s", current_user,
                      client)
                client_user.default_avatar = True

            db.session.flush()
            LOG.d("create client-user for client %s, user %s", client,
                  current_user)

        redirect_args = {}

        if state:
            redirect_args["state"] = state
        else:
            LOG.warning(
                "more security reason, state should be added. client %s",
                client)

        if scope:
            redirect_args["scope"] = scope

        auth_code = None
        if ResponseType.CODE in response_types:
            # Create authorization code
            auth_code = AuthorizationCode.create(
                client_id=client.id,
                user_id=current_user.id,
                code=random_string(),
                scope=scope,
                redirect_uri=redirect_uri,
                response_type=response_types_to_str(response_types),
            )
            db.session.add(auth_code)
            redirect_args["code"] = auth_code.code

        oauth_token = None
        if ResponseType.TOKEN in response_types:
            # create access-token
            oauth_token = OauthToken.create(
                client_id=client.id,
                user_id=current_user.id,
                scope=scope,
                redirect_uri=redirect_uri,
                access_token=generate_access_token(),
                response_type=response_types_to_str(response_types),
            )
            db.session.add(oauth_token)
            redirect_args["access_token"] = oauth_token.access_token

        if ResponseType.ID_TOKEN in response_types:
            redirect_args["id_token"] = make_id_token(
                client_user,
                nonce,
                oauth_token.access_token if oauth_token else None,
                auth_code.code if auth_code else None,
            )

        db.session.commit()

        # should all params appended the url using fragment (#) or query
        fragment = False

        if response_mode and response_mode == "fragment":
            fragment = True

        # if response_types contain "token" => implicit flow => should use fragment
        # except if client sets explicitly response_mode
        if not response_mode:
            if ResponseType.TOKEN in response_types:
                fragment = True

        # construct redirect_uri with redirect_args
        return redirect(construct_url(redirect_uri, redirect_args, fragment))