feat: templates to add gitea oauth configuration

This commit is contained in:
Aravinth Manivannan 2022-12-19 00:27:36 +05:30
parent 3f79ff8cb4
commit 968a799b35
Signed by: realaravinth
GPG key ID: AD9F0F08E855ED88
7 changed files with 418 additions and 0 deletions

118
src/pages/auth/gitea/add.rs Normal file
View file

@ -0,0 +1,118 @@
/*
* Copyright (C) 2022 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use std::cell::RefCell;
use actix_web::http::header::ContentType;
use tera::Context;
use crate::db::AddGiteaInstance;
use crate::pages::errors::*;
use crate::settings::Settings;
use crate::AppCtx;
pub use super::*;
pub struct GiteaAddInstanceTemplate {
ctx: RefCell<Context>,
}
pub const GITEA_ADD_INSTANCE: TemplateFile =
TemplateFile::new("gitea_add_instance", "pages/auth/gitea/add.html");
impl CtxError for GiteaAddInstanceTemplate {
fn with_error(&self, e: &ReadableError) -> String {
self.ctx.borrow_mut().insert(ERROR_KEY, e);
self.render()
}
}
impl GiteaAddInstanceTemplate {
pub fn new(settings: &Settings, payload: Option<&AddGiteaInstance>) -> Self {
let ctx = RefCell::new(context(settings));
if let Some(payload) = payload {
ctx.borrow_mut().insert(PAYLOAD_KEY, payload);
}
Self { ctx }
}
pub fn render(&self) -> String {
TEMPLATES
.render(GITEA_ADD_INSTANCE.name, &self.ctx.borrow())
.unwrap()
}
pub fn page(s: &Settings) -> String {
let p = Self::new(s, None);
p.render()
}
}
#[actix_web_codegen_const_routes::get(path = "PAGES.auth.gitea.add")]
#[tracing::instrument(name = "Serve add Gitea instance page", skip(ctx))]
pub async fn get_gitea_add_instance(ctx: AppCtx) -> impl Responder {
let login = GiteaAddInstanceTemplate::page(&ctx.settings);
let html = ContentType::html();
HttpResponse::Ok().content_type(html).body(login)
}
pub fn services(cfg: &mut web::ServiceConfig) {
cfg.service(get_gitea_add_instance);
cfg.service(post_gitea_add_instance);
}
#[actix_web_codegen_const_routes::post(path = "PAGES.auth.gitea.add")]
#[tracing::instrument(name = "Submit new Gitea instance", skip(payload, ctx))]
pub async fn post_gitea_add_instance(
payload: web::Form<AddGiteaInstance>,
ctx: AppCtx,
) -> PageResult<impl Responder, GiteaAddInstanceTemplate> {
let payload = payload.into_inner();
ctx.init_gitea_instance(&payload).await.map_err(|e| {
PageError::new(
GiteaAddInstanceTemplate::new(&ctx.settings, Some(&payload)),
e,
)
})?;
Ok(HttpResponse::Found()
.insert_header((http::header::LOCATION, PAGES.dash.home))
.finish())
}
#[cfg(test)]
mod tests {
use url::Url;
use super::GiteaAddInstanceTemplate;
use crate::db::AddGiteaInstance;
use crate::errors::*;
use crate::pages::errors::*;
use crate::settings::Settings;
#[test]
fn gitea_add_instnace_page_renders() {
let settings = Settings::new().unwrap();
GiteaAddInstanceTemplate::page(&settings);
let payload = AddGiteaInstance {
client_id: "foo".into(),
client_secret: "foo".into(),
url: Url::parse("https://example.org").unwrap(),
};
let page = GiteaAddInstanceTemplate::new(&settings, Some(&payload));
page.with_error(&ReadableError::new(&ServiceError::WrongPassword));
page.render();
}
}

View file

@ -0,0 +1,32 @@
/*
* Copyright (C) 2022 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use actix_web::*;
pub use super::{context, Footer, TemplateFile, PAGES, PAYLOAD_KEY, TEMPLATES};
pub mod add;
pub fn register_templates(t: &mut tera::Tera) {
for template in [add::GITEA_ADD_INSTANCE].iter() {
template.register(t).expect(template.name);
}
}
pub fn services(cfg: &mut web::ServiceConfig) {
add::services(cfg)
}

View file

@ -0,0 +1,118 @@
/*
* Copyright (C) 2022 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use std::cell::RefCell;
use actix_web::http::header::ContentType;
use tera::Context;
use crate::db::AddGiteaInstance;
use crate::pages::errors::*;
use crate::settings::Settings;
use crate::AppCtx;
pub use super::*;
pub struct GiteaAddInstanceTemplate {
ctx: RefCell<Context>,
}
pub const GITEA_SEARCH_INSTANCE: TemplateFile =
TemplateFile::new("gitea_add_instance", "pages/auth/gitea/add.html");
impl CtxError for GiteaAddInstanceTemplate {
fn with_error(&self, e: &ReadableError) -> String {
self.ctx.borrow_mut().insert(ERROR_KEY, e);
self.render()
}
}
impl GiteaAddInstanceTemplate {
pub fn new(settings: &Settings, payload: Option<&AddGiteaInstance>) -> Self {
let ctx = RefCell::new(context(settings));
if let Some(payload) = payload {
ctx.borrow_mut().insert(PAYLOAD_KEY, payload);
}
Self { ctx }
}
pub fn render(&self) -> String {
TEMPLATES
.render(GITEA_SEARCH_INSTANCE.name, &self.ctx.borrow())
.unwrap()
}
pub fn page(s: &Settings) -> String {
let p = Self::new(s, None);
p.render()
}
}
#[actix_web_codegen_const_routes::get(path = "PAGES.auth.gitea.add")]
#[tracing::instrument(name = "Serve add Gitea instance page", skip(ctx))]
pub async fn get_gitea_add_instance(ctx: AppCtx) -> impl Responder {
let login = GiteaAddInstanceTemplate::page(&ctx.settings);
let html = ContentType::html();
HttpResponse::Ok().content_type(html).body(login)
}
pub fn services(cfg: &mut web::ServiceConfig) {
cfg.service(get_gitea_add_instance);
cfg.service(post_gitea_add_instance);
}
#[actix_web_codegen_const_routes::post(path = "PAGES.auth.gitea.add")]
#[tracing::instrument(name = "Submit new Gitea instance", skip(payload, ctx))]
pub async fn post_gitea_add_instance(
payload: web::Form<AddGiteaInstance>,
ctx: AppCtx,
) -> PageResult<impl Responder, GiteaAddInstanceTemplate> {
let payload = payload.into_inner();
ctx.init_gitea_instance(&payload).await.map_err(|e| {
PageError::new(
GiteaAddInstanceTemplate::new(&ctx.settings, Some(&payload)),
e,
)
})?;
Ok(HttpResponse::Found()
.insert_header((http::header::LOCATION, PAGES.dash.home))
.finish())
}
#[cfg(test)]
mod tests {
use url::Url;
use super::GiteaAddInstanceTemplate;
use crate::db::AddGiteaInstance;
use crate::errors::*;
use crate::pages::errors::*;
use crate::settings::Settings;
#[test]
fn gitea_add_instnace_page_renders() {
let settings = Settings::new().unwrap();
GiteaAddInstanceTemplate::page(&settings);
let payload = AddGiteaInstance {
client_id: "foo".into(),
client_secret: "foo".into(),
url: Url::parse("https://example.org").unwrap(),
};
let page = GiteaAddInstanceTemplate::new(&settings, Some(&payload));
page.with_error(&ReadableError::new(&ServiceError::WrongPassword));
page.render();
}
}

View file

@ -19,6 +19,7 @@ use actix_web::*;
pub use super::{context, Footer, TemplateFile, PAGES, PAYLOAD_KEY, TEMPLATES};
pub mod gitea;
pub mod login;
pub mod register;
#[cfg(test)]
@ -30,12 +31,14 @@ pub fn register_templates(t: &mut tera::Tera) {
for template in [AUTH_BASE, login::LOGIN, register::REGISTER].iter() {
template.register(t).expect(template.name);
}
gitea::register_templates(t);
}
pub fn services(cfg: &mut web::ServiceConfig) {
cfg.service(signout);
register::services(cfg);
login::services(cfg);
gitea::services(cfg);
}
#[actix_web_codegen_const_routes::get(

View file

@ -41,6 +41,25 @@ impl Pages {
}
}
#[derive(Serialize)]
/// Gitea authentication routes
pub struct Gitea {
/// add Gitea instance route
pub add: &'static str,
/// search Gitea instance route
pub search: &'static str,
}
impl Gitea {
/// create new instance of Authentication route
pub const fn new() -> Self {
let add = "/gitea/add";
let search = "/gitea/search";
Self { add, search }
}
}
#[derive(Serialize)]
/// Authentication routes
pub struct Auth {
@ -50,6 +69,8 @@ pub struct Auth {
pub login: &'static str,
/// registration route
pub register: &'static str,
/// gitea authentication routes
pub gitea: Gitea,
}
impl Auth {
@ -58,10 +79,12 @@ impl Auth {
let login = "/login";
let logout = "/logout";
let register = "/join";
let gitea = Gitea::new();
Auth {
logout,
login,
register,
gitea,
}
}
}

View file

@ -0,0 +1,62 @@
{% extends 'authbase' %}
{% block login %}
<h2>Add Gitea Instance</h2>
<form action="{{ page.auth.gitea.add }}" method="POST" class="auth-form" accept-charset="utf-8">
{% include "error_comp" %}
<label class="auth-form__label" for="url">
Gitea URL
<input
class="auth-form__input"
name="url"
autofocus
required
id="url"
type="url"
{% if payload.url %}
value={{ payload.url }}
{% endif %}
/>
</label>
<label class="auth-form__label" for="client_id">
Client ID
<input
class="auth-form__input"
name="client_id"
autofocus
required
id="client_id"
type="text"
{% if payload.client_id %}
value={{ payload.client_id }}
{% endif %}
/>
</label>
<label class="auth-form__label" for="client_secret">
Client Secret
<input
class="auth-form__input"
name="client_secret"
required
id="client_secret"
type="password"
{% if payload.client_secret %}
value={{ payload.client_secret }}
{% endif %}
/>
</label>
<div class="auth-form__action-container">
<button class="auth-form__submit" type="submit">Login</button>
</div>
</form>
<!--
<p class="auth-form__alt-action">
New to LibrePages?
<a href="{{ page.auth.register }}">Create an account </a>
</p>
-->
{% endblock %}

View file

@ -0,0 +1,62 @@
{% extends 'authbase' %}
{% block login %}
<h2>Add Gitea Instance</h2>
<form action="{{ page.auth.gitea.add }}" method="POST" class="auth-form" accept-charset="utf-8">
{% include "error_comp" %}
<label class="auth-form__label" for="url">
Gitea URL
<input
class="auth-form__input"
name="url"
autofocus
required
id="url"
type="url"
{% if payload.url %}
value={{ payload.url }}
{% endif %}
/>
</label>
<label class="auth-form__label" for="client_id">
Client ID
<input
class="auth-form__input"
name="client_id"
autofocus
required
id="client_id"
type="text"
{% if payload.client_id %}
value={{ payload.client_id }}
{% endif %}
/>
</label>
<label class="auth-form__label" for="client_secret">
Client Secret
<input
class="auth-form__input"
name="client_secret"
required
id="client_secret"
type="password"
{% if payload.client_secret %}
value={{ payload.client_secret }}
{% endif %}
/>
</label>
<div class="auth-form__action-container">
<button class="auth-form__submit" type="submit">Login</button>
</div>
</form>
<!--
<p class="auth-form__alt-action">
New to LibrePages?
<a href="{{ page.auth.register }}">Create an account </a>
</p>
-->
{% endblock %}