Add code to load client app data, add authorization page

master
teknomunk 1 year ago
parent 75843983d6
commit 01734cd103

@ -8,46 +8,50 @@
#include "form.h"
#include "model/client_app.h"
bool route_mastodon_api( struct http_request* req )
bool handle_mastodon_api_apps( struct http_request* req )
{
if( http_request_route( req, "apps" ) ) {
if( http_request_route_method( req, "POST" ) ) {
FILE* data = http_request_get_request_data( req );
printf( "OAuth2 app\n" );
struct form_parser* fp = form_pull_parser_new( data );
if( !fp ) { return false; }
char* client_name = NULL;
char* redirect_uris = NULL;
FILE* data = http_request_get_request_data( req );
struct form_parser* fp = form_pull_parser_new( data );
if( !fp ) { return false; }
char* client_name = NULL;
char* redirect_uris = NULL;
char* key;
while( key = form_pull_parser_read_key( fp ) ) {
if( 0 == strcmp( "client_name", key ) ) {
client_name = strdup( form_pull_parser_read_value(fp) );
} else if( 0 == strcmp( "redirect_uris", key ) ) {
redirect_uris = strdup( form_pull_parser_read_value(fp) );
} else {
printf( "key: %s\n", key );
printf( "value: %s\n", form_pull_parser_read_value(fp) );
}
}
char* key;
while( key = form_pull_parser_read_key( fp ) ) {
if( 0 == strcmp( "client_name", key ) ) {
client_name = strdup( form_pull_parser_read_value(fp) );
} else if( 0 == strcmp( "redirect_uris", key ) ) {
redirect_uris = strdup( form_pull_parser_read_value(fp) );
} else {
printf( "key: %s\n", key );
printf( "value: %s\n", form_pull_parser_read_value(fp) );
}
}
form_pull_parser_release(fp);
form_pull_parser_release(fp);
struct client_app* app = client_app_new( client_name );
struct client_app* app = client_app_new( client_name );
http_request_send_headers( req, 200, "application/json", true );
FILE* f = http_request_get_response_body( req );
http_request_send_headers( req, 200, "application/json", true );
FILE* f = http_request_get_response_body( req );
#define RENDER
#include "controller/mastodon_api/apps.json.inc"
#undef RENDER
#define RENDER
#include "controller/mastodon_api/apps.json.inc"
#undef RENDER
free(client_name);
free(redirect_uris);
free(client_name);
free(redirect_uris);
return true;
}
return true;
bool route_mastodon_api( struct http_request* req )
{
if( http_request_route( req, "apps" ) ) {
if( http_request_route_method( req, "POST" ) ) {
return handle_mastodon_api_apps(req);
}
}
return false;

@ -1,20 +1,127 @@
#include "oauth.h"
#include "http_server/http_request.h"
#include "model/client_app.h"
#include "form.h"
#include <stdlib.h>
#include <string.h>
bool route_oauth_authorize( struct http_request* req )
{
http_request_send_headers( req, 200, "application/json", true );
char* client_id = NULL;
char* redirect_uri = NULL;
char* response_type = NULL;
bool result = true;
struct {
bool read;
bool write;
bool follow;
} scopes = { false, false, false };
// Parse query parameters
{
const char* key;
while( key = http_request_route_query_key(req) ) {
if( 0 == strcmp(key,"client_id") ) {
client_id = strdup(http_request_route_query_value(req));
} else if( 0 == strcmp(key,"redirect_uri") ) {
redirect_uri = strdup(http_request_route_query_value(req));
// Validate redirection uri
bool valid = false;
if( 0 == strncmp("oauth2redirect://",redirect_uri,17) ) {
valid = true;
}
if( !valid ) {
result = false; goto cleanup;
}
} else if( 0 == strcmp(key,"response_type") ) {
if( 0 != strcmp(http_request_route_query_value(req),"code") ) {
result = false; goto cleanup;
}
} else if( 0 == strcmp(key,"scope") ) {
char* scope = strdup(http_request_route_query_value(req));
char* resume = scope;
char* item;
while( item = strtok_r( NULL, " ", &resume ) ) {
if( 0 == strcmp(item,"read") ) {
scopes.read = true;
} else if( 0 == strcmp(item,"write") ) {
scopes.write = true;
} else if( 0 == strcmp(item,"follow") ) {
scopes.follow = true;
} else {
free(scope);
result = false; goto cleanup;
}
}
free(scope);
} else {
printf( "key=%s\n", key );
printf( "value=%s\n\n", http_request_route_query_value(req) );
}
}
}
struct client_app* app = client_app_from_id( client_id );
if( !app) {
result =false; goto cleanup;
}
http_request_send_headers( req, 200, "text/html", true );
FILE* f = http_request_get_response_body( req );
#define RENDER
#include "view/login.html.inc"
#include "view/authorize.html.inc"
#undef RENDER
return true;
result = true;
cleanup:
free(client_id);
free(redirect_uri);
free(response_type);
return result;
}
bool route_oauth_do_authorize( struct http_request* req )
{
FILE* body = http_request_get_request_data(req);
struct form_parser* fp = form_pull_parser_new(body);
if( !fp ) { return false; }
char* password = NULL;
char* key;
while( key = form_pull_parser_read_key( fp ) ) {
if( 0 == strcmp(key,"password") ) {
password = strdup(form_pull_parser_read_value(fp));
printf( "password: %s\n", password );
}
}
form_pull_parser_release(fp);
if( !password ) {
return false;
}
printf( "\nTODO: perform authorization\n\n" );
free(password);
return false;
}
bool route_oauth( struct http_request* req )
{
if( http_request_route( req, "/authorize" ) ) {
return route_oauth_authorize(req);
if( http_request_route_method(req,"POST") ) {
return route_oauth_do_authorize(req);
} else if( http_request_route( req, "?" ) ) {
return route_oauth_authorize(req);
}
}
return false;

@ -1 +1 @@
Subproject commit ac013e14cae0f377356ef8a1ae002c465d53a306
Subproject commit 897cc85f52f00ce959a26d3a787aa887a37e0aad

@ -1,9 +1,51 @@
#include "client_app.h"
#include "json/json.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct client_app* client_app_from_id( const char* client_id )
{
char filename[512];
snprintf( filename, 512, "data/client_apps/%s.json", client_id );
FILE* f = fopen(filename,"r");
if( !f ) {
return NULL;
}
struct client_app* app = malloc(sizeof(struct client_app));
app->client.name = NULL;
app->client.id = strdup(client_id);
app->client.secret = NULL;
struct json_pull_parser* jpp = json_pull_parser_new( f );
if( !jpp ) {
return NULL;
}
int s[5];
if( !json_pull_parser_begin_object( jpp, &s[0] ) ) {
return NULL;
}
char* key;
while( key = json_pull_parser_read_object_key(jpp) ) {
if( 0 == strcmp(key,"secret") ) {
app->client.secret = json_pull_parser_read_string(jpp);
} else if( 0 == strcmp(key,"name") ) {
app->client.name = json_pull_parser_read_string(jpp);
}
}
free(key);
if( !json_pull_parser_end_object(jpp, &s[0] ) ) {
client_app_free(app);
return NULL;
}
return app;
}
struct client_app* client_app_new( const char* client_name )
{
char id[33];
@ -36,6 +78,9 @@ void client_app_save( struct client_app* app )
snprintf( tmp_filename, 512, "%s.tmp-%d", filename, rand() );
FILE* f = fopen(tmp_filename, "w" );
if( !f ) {
return;
}
#define RENDER
#include "model/client_app.json.inc"
#undef RENDER
@ -43,3 +88,11 @@ void client_app_save( struct client_app* app )
rename( tmp_filename, filename );
}
void client_app_free( struct client_app* app )
{
free(app->client.name);
free(app->client.secret);
free(app->client.id);
free(app);
}

@ -9,7 +9,8 @@ struct client_app
} client;
};
struct client_app* load_client_app_from_id( const char* client_id );
struct client_app* client_app_from_id( const char* client_id );
struct client_app* client_app_new( const char* client_name );
void client_app_save( struct client_app* app );
void client_app_free( struct client_app* app );

@ -1,7 +1,4 @@
{
"client": {
"id": "%s{app->client.id}",
"secret": "%s{app->client.secret}",
"name": "%s{app->client.name}"
}
"secret": "%s{app->client.secret}",
"name": "%s{app->client.name}"
}

@ -0,0 +1,26 @@
<h1>App Authorization</h1>
<h2>Requested Permissions</h2>
<ul>
%( if( scopes.read ) { )
<li>
Read posts
</li>
%( } )
%( if( scopes.write ) { )
<li>
Write posts
</li>
%( } )
%( if( scopes.follow ) { )
<li>
Follow other accounts
</li>
%( } )
</ul>
<form action="/oauth/authorize" method="post">
Password: <input type='password' name='password'/><br/>
<input type="submit" />
</form>

@ -1 +0,0 @@
TODO: show a login page
Loading…
Cancel
Save